Android:使用Moshi适配器解析内部非结构化Json

Android:使用Moshi适配器解析内部非结构化Json,android,json,gson,retrofit,moshi,Android,Json,Gson,Retrofit,Moshi,我很难解析JSON的某些内部部分(使用Moshi),这些内部部分可能变化很大,并且是高度非结构化的。总的看来: response: { items: [{ type: "typeA", data: { "1563050214700-001": { foo: 123 .... } } }, { type: "typeB",

我很难解析JSON的某些内部部分(使用Moshi),这些内部部分可能变化很大,并且是高度非结构化的。总的看来:

response: {
    items: [{
        type: "typeA",
        data: {
            "1563050214700-001": {
                foo: 123 ....
            }
        }
    }, {
        type: "typeB",
        data: {
            "1563050214700-002": {[
                // differs a lot from previous one
                {bar: 123 .... }
            ]}
        }
    }]
}
data class Response(
    val items: Map<String,List<Item?>>?
) {
    data class Item(
        val type: String?,
        val data: Map<String,List<DataItem?>>?
    ) {
        data class DataItem(
            // members highly unstructured
        )
    }
}
数据类结构如下所示:

response: {
    items: [{
        type: "typeA",
        data: {
            "1563050214700-001": {
                foo: 123 ....
            }
        }
    }, {
        type: "typeB",
        data: {
            "1563050214700-002": {[
                // differs a lot from previous one
                {bar: 123 .... }
            ]}
        }
    }]
}
data class Response(
    val items: Map<String,List<Item?>>?
) {
    data class Item(
        val type: String?,
        val data: Map<String,List<DataItem?>>?
    ) {
        data class DataItem(
            // members highly unstructured
        )
    }
}

我如何做到这一点?任何示例或参考实现都会有所帮助。

欢迎使用多态JSON解析问题word

我们正在编写自己的JSON适配器,如下所示:

internal class CardJsonAdapter(
        moshi: Moshi
) : JsonAdapter<Card>() {

    private val cardTypeAdapter = moshi.adapter(Card.Type::class.java)
    private val amountsWithActionAdapter = moshi.adapter(AmountsWithActionCard::class.java)
    private val backgroundImageCardAdapter = moshi.adapter(BackgroundImageCard::class.java)

    @Suppress("TooGenericExceptionCaught")
    override fun fromJson(reader: JsonReader): Card = try {

        @Suppress("UNCHECKED_CAST")
        val jsonMap = reader.readJsonValue() as Map<String, Any?>
        val type = cardTypeAdapter.fromJsonValue(jsonMap["type"])
        createCardWithType(type, jsonMap)

    } catch (error: Exception) {
        if (BuildConfig.DEBUG) {
            Log.w("CardJsonAdapter", "Failed to parse card", error)
        }
        // Try not to break the app if we get unexpected data: ignore errors and return a placeholder card instead.
        UnknownCard
    }

    override fun toJson(writer: JsonWriter, value: Card?) {
        throw NotImplementedError("This adapter cannot write cards to JSON")
    }

    private fun createCardWithType(type: Type?, jsonMap: Map<String, Any?>) = when (type) {
        null -> UnknownCard
        Type.AMOUNTS_WITH_ACTION -> amountsWithActionAdapter.fromJsonValue(jsonMap)!!
        Type.BACKGROUND_IMAGE_WITH_TITLE_AND_MESSAGE -> backgroundImageCardAdapter.fromJsonValue(jsonMap)!!
    }
}
内部类CardJsonAdapter(
摩希:摩希
):JsonAdapter(){
private val cardTypeAdapter=moshi.adapter(Card.Type::class.java)
private val amountsWithActionAdapter=moshi.adapter(AmountsWithActionCard::class.java)
private val backgroundImageCardAdapter=moshi.adapter(BackgroundImageCard::class.java)
@抑制(“TooGenericeExceptionCapture”)
override fun fromJson(reader:JsonReader):Card=try{
@抑制(“未选中的_CAST”)
val jsonMap=reader.readJsonValue()作为映射
val type=cardTypeAdapter.fromJsonValue(jsonMap[“type”])
createCardWithType(类型,jsonMap)
}捕获(错误:异常){
if(BuildConfig.DEBUG){
Log.w(“CardJsonAdapter”,“解析卡失败”,错误)
}
//如果收到意外数据,请尝试不要中断应用程序:忽略错误并返回占位符卡。
未知卡片
}
重写fun-toJson(writer:JsonWriter,value:Card?){
抛出NotImplementedError(“此适配器无法将卡写入JSON”)
}
private fun createCardWithType(类型:type?,jsonMap:Map)=何时(类型){
空->未知卡片
键入.AMOUNTS\u并单击\u ACTION->amountsWithActionAdapter.fromJsonValue(jsonMap)!!
键入.BACKGROUND\u IMAGE\u,带有标题和消息->backgroundImageCardAdapter.fromJsonValue(jsonMap)!!
}
}
然而,它不再是必需的。Moshi现在支持多态JSON解析-制作自定义适配器

class YourAdapter {

@FromJson
fun fromJson(reader: JsonReader, itemsAdapter: JsonAdapter<ItemsResponse>): List<ItemsResponse>? {
    val list = ArrayList<ItemsResponse>()
    if (reader.hasNext()) {
        val token = reader.peek()
        if (token == JsonReader.Token.BEGIN_ARRAY) {
            reader.beginArray()
            while (reader.hasNext()) {
                val itemResponse = itemsAdapter.fromJsonValue(reader.readJsonValue())
                itemsResponse?.let {
                    list.add(itemResponse)
                }
            }
            reader.endArray()
        }
    }
    return list
}
}
class适配器{
@FromJson
来自JSON的乐趣(reader:JsonReader,itemsAdapter:JsonAdapter):列表{
val list=ArrayList()
if(reader.hasNext()){
val-token=reader.peek()
if(token==JsonReader.token.BEGIN\u数组){
reader.beginArray()
while(reader.hasNext()){
val itemResponse=itemsAdapter.fromJsonValue(reader.readJsonValue())
项目响应?让我们{
list.add(itemResponse)
}
}
reader.endArray()
}
}
返回列表
}
}

谢谢。然而,在本文中的示例中,不同类型的有效负载有一个区分“动作”:“谈话”、“动作”:“流”等的字段。当没有这些区别并且完全匹配不同的有效负载模式时,这种方法能起作用吗?我不这么认为。您必须实现对所有可能的解析解决方案的迭代,并自己选择正确的解决方案。你对BE有影响吗?你能让他们给JSON增加一些区别吗?不幸的是,我不能改变。在任何情况下,您的响应都是有用的(在多态解析上),因此将标记为已接受。谢谢