moshi定制JsonAdapter的问题,用于跳过不良元素

时间:2019-12-30 09:05:25

标签: android kotlin moshi

我有一个moshi自定义json适配器,用于跳过以下不良元素:

class SkipBadElementsListAdapter(private val elementAdapter: JsonAdapter<Any?>) :
JsonAdapter<List<Any?>>() {
object Factory : JsonAdapter.Factory {
    override fun create(
        type: Type,
        annotations: Set<Annotation>,
        moshi: Moshi
    ): JsonAdapter<*>? {
        if (annotations.isNotEmpty() || Types.getRawType(type) != List::class.java) {
            return null
        }
        val elementType = Types.collectionElementType(type, List::class.java)
        val elementAdapter = moshi.adapter<Any?>(elementType)
        return SkipBadElementsListAdapter(elementAdapter).nullSafe()
    }
}

override fun fromJson(reader: JsonReader): List<Any?>? {

    val result = mutableListOf<Any?>()
    reader.beginArray()
    while (reader.hasNext()) {
        try {
            val peeked = reader.peekJson()
            result += elementAdapter.fromJson(peeked)
        } catch (ignored: JsonDataException) {
            Timber.tag("JsonParseError").d(ignored.toString())
        }
        reader.skipValue()
    }
    reader.endArray()
    return result

}

override fun toJson(writer: JsonWriter, value: List<Any?>?) {

    if (value == null) {
        throw NullPointerException("value was null! Wrap in .nullSafe() to write nullable values.")
    }
    writer.beginArray()
    for (i in value.indices) {
        elementAdapter.toJson(writer, value[i])
    }
    writer.endArray()
}

}

但是添加此自定义json适配器后,我在firebase中收到很多致命错误:

Fatal Exception: java.lang.AssertionError
   at com.squareup.moshi.JsonUtf8Reader.<init>(JsonUtf8Reader.java:118)
   at com.squareup.moshi.JsonUtf8Reader.peekJson(JsonUtf8Reader.java:1076)
   at ir.part.app.signal.core.util.api.SkipBadElementsListAdapter.fromJson(SkipBadElementsListAdapter.java:30)
   at ir.part.app.signal.core.util.api.SkipBadElementsListAdapter.fromJson(SkipBadElementsListAdapter.java:7)
   at com.squareup.moshi.JsonAdapter$2.fromJson(JsonAdapter.java:137)
   at ir.part.app.signal.core.model.SignalListResponseJsonAdapter.fromJson(SignalListResponseJsonAdapter.java:41)
   at ir.part.app.signal.core.model.SignalListResponseJsonAdapter.fromJson(SignalListResponseJsonAdapter.java:17)
   at com.squareup.moshi.JsonAdapter$2.fromJson(JsonAdapter.java:137)
   at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:45)
   at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:27)
   at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
   at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121)
   at com.google.firebase.perf.network.zzh.onResponse(zzh.java:22)
   at okhttp3.RealCall$AsyncCall.execute(RealCall.java:203)
   at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
   at java.lang.Thread.run(Thread.java:776)

我查看了moshi lib代码,并猜测“ sourcePeek.require”中出现了问题:

    JsonUtf8Reader(JsonUtf8Reader copyFrom) {
    ...
    // Make sure our buffer has as many bytes as the source's buffer. This is necessary because
    // JsonUtf8Reader assumes any data it has peeked (like the peekedNumberLength) are buffered.
    try {
      sourcePeek.require(copyFrom.buffer.size());
    } catch (IOException e) {
      throw new AssertionError();
    }
}

我的自定义moshi适配器怎么了?!我想跳过json从服务器接收到的数据列表中的错误元素并显示正确的项目。

1 个答案:

答案 0 :(得分:1)

跳过适配器不知道要跳过多少。您希望它跳到当前列表元素的末尾,因为崩溃可能会使JsonReader部分通过复杂的对象离开。

通过将peekJson()传递给委托适配器并始终跳过而不管是否存在异常来解决。