如何在 Moshi 中跳过 JSON 属性?

Posted

技术标签:

【中文标题】如何在 Moshi 中跳过 JSON 属性?【英文标题】:How to skip JSON properties in Moshi? 【发布时间】:2021-01-18 13:45:37 【问题描述】:

我正在尝试使用com.squareup.moshi (v1.10.0) 在我用 Kotlin 编写的 android 应用程序中实现 JSON 解析。

在 JSON 文件中,有一些属性对我来说并不有趣。比方说,我只需要能够在地图上标记地点的位置,JSON 看起来像这样:

    "location":
         "address":
            "country":"..."
         ,
         "position":
            "lat":47.469866,
            "lon":19.062435
         
     

如果我是对的,如果我想解析 JSON,Kotlin 中的数据类应该是这样的:

   @Parcelize
   data class Location(
       val address: Address,
       val position: Position
   ): Parcelable

   @Parcelize
   data class Address(
       val country: String
   ): Parcelable

   @Parcelize
   data class Position(
       val lat: Double,
       val lon: Double
   ): Parcelable

在Moshi's documentation 中,我可以找到transient 关键字来跳过在Kotlin 中用作注释的值(@Transient)。正如文档所说:

在编写 JSON 时会省略瞬态字段。读取 JSON 时,即使 JSON 包含该字段的值,也会跳过该字段。相反,它将获得一个默认值。

是不是说如果我不想拥有地址对象,就应该使用下面的代码?

   @Parcelize
   data class Location(
       @Transient val address: Address? = null,
       val position: Position
   ): Parcelable

另外,一般来说呢?如果我在 JSON 对象中有大量属性但我知道我只需要 'position' 对象怎么办?我是否仍需要创建 null 值来逐字段解析 JSON 文件?

【问题讨论】:

【参考方案1】:

我认为您正在寻找类似于 GSON 的 @Expose annotations 的东西,其中所有模型字段都被排除在解析之外,除了那些带注释的字段。

此功能目前在 Moshi 中不可用,因此您当前使用 @Transient 注释的实现似乎是最佳解决方案。 (See Moshi issues conversation here.)

额外的思考:

您可能还希望在瞬态字段上使用@IgnoredOnParcel,因为您正在实现parcelable 接口。 (查看here 以获得一些实现指针。)

或者,您可以将数据模型分成 2 个模型 - 一个用于您的应用程序,一个反映服务器 (JSON) 架构(就像您在上面所做的那样)。您的应用程序(可以实现 parcelable)的主要数据模型将仅包含您使用的字段(例如,位置字段)。当您解析数据时,然后使用一些简单的适配器将该数据转换为您的主要数据模型。 (无论如何,这通常是一种很好的做法,因为服务器端模式是固有的更改。这样,JSON 模式中的任何更改都不会在整个代码中产生任何连锁反应。)

【讨论】:

感谢您的回答!你写了一些我什至没有想到的东西。你超出了我的预期,这是肯定的:D 这个缺少的@Expose 注释非常重要,它允许在序列化的两侧表示单个模型类。例如同一个类既可以用于远程源的序列化,也可以用于本地 Room 实体,大大简化了维护。不幸的是,rom 和 moshi 一样理解瞬变,当你真正想要的是 Moshi 忽略本地字段,而不是 Room。【参考方案2】:

https://github.com/square/moshi#omit-fields-with-transient

省略具有瞬态的字段 一些模型声明了不应包含在 JSON 中的字段。例如,假设我们的 21 点手牌有一个包含牌数总和的总字段:

public final class BlackjackHand 
  private int total;

  ...

默认情况下,编码 JSON 时会发出所有字段,解码 JSON 时会接受所有字段。通过添加 Java 的瞬态关键字来防止包含字段:

public final class BlackjackHand 
  private transient int total;

  ...

在编写 JSON 时会省略瞬态字段。读取 JSON 时,即使 JSON 包含该字段的值,也会跳过该字段。相反,它将获得一个默认值。

【讨论】:

以上是关于如何在 Moshi 中跳过 JSON 属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 JSON 数据框中跳过重复值和空白值并存储到数组中?

如何在 spring-mvc 中跳过杰克逊时区校正?

如何在函数调用中跳过可选参数?

如何在推送事件中跳过 GitHub Actions 作业?

如何根据某些条件在 MSSQL 游标中跳过一行(迭代)?

WPF - 如何在标签导航中跳过标签?