How to parse a json list of multiple type in Moshi

雨燕双飞 提交于 2021-01-21 14:30:52

问题


Got a json list mixed with plain String and Image object like this:

 {
  "mixList": [
    "string",
    {
      "imageUrl": "http://...",
      "height": 320,
      "width": 480
    }
  ]
}

How to parse with Moshi?

I would expect to have a List<Data>, where StringData extends Data and ImageData extends Data


回答1:


I've solved this problem using Moshi with a CustomAdaptor. After a lot of research I wasn't able to find a better "out-of-the-box" solution. This solutions is in kotlin but can easily be ported to Java as well.

First let's define the types we are trying to parse here. I'll call the wrapper type, that contains the mixList, Response:

@JsonClass(generateAdapter = true)
data class Response(val mix_types: Data)

And the 2 different types that can be inside the list StringData and ImageData:

sealed class Data {
    data class StringData(val value: String) : Data()

    @JsonClass(generateAdapter = true)
    data class ImageData(
        val imageUrl: String,
        val height: Int,
        val width: Int
    ) : Data()
}

As I'm using Moshi code-gen, so I have annotated Response and ImageData with @JsonClass(generateAdapter = true) so that Moshi will generate the adapters for these types(and I'll leverage this in my custom adapter).

I want to provide my own custom adapter to the Data type, and I won't also want the adapter Moshi would generate for the StringData type, since this is precisely what I want to serialise/deserialise into a String, so I won't annotate these classes.

Now I'm gonna write my custom adapter like this:

class DataCustomAdapter {
    @FromJson
    fun fromJson(jsonReader: JsonReader, delegate: JsonAdapter<ImageData>): Data? {
        return if (jsonReader.peek() == BEGIN_OBJECT) {
            delegate.fromJson(jsonReader)
        } else {
            StringData(jsonReader.nextString())
        }
    }

    @ToJson
    fun toJson(jsonWriter: JsonWriter, data: Data, delegate: JsonAdapter<ImageData>) {
        when (data) {
            is ImageData -> delegate.toJson(jsonWriter, data)
            is StringData -> jsonWriter.value(data.value)
        }
    }
}

all it's missing now is to register the custom adapter with Moshi:

private val moshi = Moshi.Builder()
    .add(DataCustomAdapter())
    .build()


来源:https://stackoverflow.com/questions/40122296/how-to-parse-a-json-list-of-multiple-type-in-moshi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!