如何在Moshi中解析多种类型的json列表 [英] How to parse a json list of multiple type in Moshi

查看:494
本文介绍了如何在Moshi中解析多种类型的json列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

得到一个混合了纯String和Image对象的json列表,如下所示:

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

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

如何与Moshi解析?

How to parse with Moshi?

我希望有一个List<Data>, 其中StringData extends DataImageData extends Data

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

推荐答案

我已经解决了使用MoshiCustomAdaptor的问题.经过大量研究,我无法找到更好的即用型"解决方案.解决方案.此解决方案位于kotlin中,但也可以轻松移植到Java.

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.

首先让我们定义我们要在此处解析的类型.我将调用包装器类型,其中包含mixListResponse:

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)

以及可以在列表StringDataImageData中的2种不同类型:

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()
}

由于我使用的是Moshi代码源,因此我在ResponseImageData处加上了@JsonClass(generateAdapter = true)注释,以便Moshi会为这些类型的适配器生成适配器(我将在我的自定义适配器中使用它)

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).

我想为Data类型提供自己的自定义适配器,并且我也不希望Moshi为StringData类型生成适配器,因为这正是我要序列化/反序列化为字符串,所以我不会注释这些类.

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)
        }
    }
}

现在所缺少的就是向Moshi注册自定义适配器:

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

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

这篇关于如何在Moshi中解析多种类型的json列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆