如何使用Gson生成pojo,并将部分保留为原始json字符串?

时间:2019-01-25 17:15:17

标签: android kotlin gson

具有jsonString

{
  "itemType": "List",

  "stream": [
    {
      "id": "b3d3841b-558a-3859-b6b5-bdd50a04469b",
      "type": "CONTENT",
      "content": {
        "author": "xxxxxxx",
        "contentType": "STORY",

        "Url": "http://www.source/"
        "coreBody": "long long long ...",

      }
    },
    {
        "id": "63bea92a-eb21-3a17-a4ef-88457ec79e24",
        "type": "CONTENT",
        "content": {
          "author": "yyyyyyyy",
          "contentType": "STORY",
          "Url": "http://www.source/"
          "coreBody": "long long long ...",

        }
    },
    {
      "id": "cfd9b4ae-fbce-3ec5-99f5-c3747b9f287f",
      "type": "CONTENT",
      "content": {
        "author": "zzzzzzzzzz",
        "contentType": "STORY",
        "Url": "http://www.source/"
        "coreBody": "long long long ...",

      }
    }
  ]
}

并将gson.fromJson()与StreamItem类一起使用(具有Item类成员,该成员具有ItemContent类成员),

val gson = Gson()
var parsedResult = gson.fromJson(jsonString, StreamItem::class.java)   

它工作正常。

@ApiSerializable
data class StreamItem(
    @SerializedName(“itemType")
    val itemType: String,

    @SerializedName("stream")
    val items: List<Item>
)



@ApiSerializable
data class Item (  
    @SerializedName("id")
    val id: String,

    @SerializedName("type")
    val type: String?,

    @SerializedName("content")
    var content: ItemContent  
) { 

    fun getType(): String {
        return type
    }

    fun getId(): String {
        return id
    }

    fun getContent(): ItemContent {
        return content
    }
}

@ApiSerializable
data class ItemContent  (

    @SerializedName("Url")
    val Url: String?,  

    @SerializedName("author")
    val author: String?,

    @SerializedName("contentType")
    var contentType: String?,

    @SerializedName("coreBody")
    val coreBody: String?

     ………    
}

但是现在需要首先将相应内容的原始json字符串存储到数据库中,然后传递。

确保我们可以从生成的ItemContent pojo中重建json字符串,但是认为在Gson解析过程中直接获取原始json字符串可能更有效(真正的“ content” json字符串要复杂得多,并且比此处的示例json大),

因此使用Gson解析类类型StreamItem_lite,其内容部分为String。

@ApiSerializable
data class StreamItem_lite(
    @SerializedName(“itemType")
    val itemType: String,

    @SerializedName("stream")
    val items: List<Item_lite>
)

@ApiSerializable
data class Item_lite (  // only used for generating un parsed content json string
    @SerializedName("id")
    val id: String,

    @SerializedName("type")
    val type: String?,

    @SerializedName("content")
    var content: String?  //content json string
)  { 

    fun getType(): String {
        return type

    }

    fun getId(): String {
        return id
    }

    fun getContent(): String {
        return content
    }
}

然后

val gson = Gson()
var parsedResult = gson.fromJson(jsonString, StreamItem_lite::class.java)   

但它不起作用并崩溃

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 3206 path $.stream[0].content

如何在生成的pojo中使用Gson获取部分原始json?

更新: 谢谢@ tmm1 https://github.com/google/gson/issues/1368Using GSON do not parse a field, only keep it with the json raw string

它可以做到:

class RawJsonAdapter: TypeAdapter<String>() {
    override fun write(out: JsonWriter?, value: String?) {
        out?.jsonValue(value)
    }
    override fun read(reader: JsonReader?): String {
        return JsonParser().parse(reader).toString()
    }
}

用法,替换为:

@SerializedName("content")
var content: String?  //content json string

具有:

@JsonAdapter(RawJsonAdapter::class)
val content: String? = null

但解析时间不会有太大变化:

+++ parse StreamItem      time: 125, items?.size: 20
+++ parse StreamItem_lite time: 110, items?.size: 20

并且将itemContent放入json只需要

+++ gsonBuilder.toJson(itemContent) time: 3

是否有更好/更有效的方法,或者创建一个TypeAdapter值得不付出努力?

0 个答案:

没有答案