Moshi + Retrofit - 处理未知类型的 JSON 响应

3

我正在使用 Moshi,以下是我的数据类

@JsonClass(generateAdapter = true)
data class A (
    @Json(name = "_id")
    val id: String?,
    @Json(name = "b")
    val b: B? = null
)

@JsonClass(generateAdapter = true)
data class B (
    @Json(name = "_id")
    val id: String?,
    @Json(name = "foo")
    val foo: String? = null
    @Json(name = "c")
    val c: C? = null
)

@JsonClass(generateAdapter = true)
data class C (
    @Json(name = "_id")
    val id: String?,
    @Json(name = "bar")
    val bar: String? = null
)

我的API有时只返回对象的ID,而其他时候则返回实际对象。例如,当我获取对象A时,有时会返回如下结果:
{
    _id: "111111111",
    b: {
        _id: "222222222",
        foo: "foo",
        c: {
            _id: "333333333",
            bar: "bar"
        }
    }
}

但有时它可能会返回其他结果

{
    _id: "111111111",
    b: "222222222"
}

或者

{
    _id: "111111111",
    b: {
        _id: "222222222",
        foo: "foo",
        c: "333333333"
    }
}

从我们所看到的,它可以返回表示对象的字符串或已填充对象本身。如何创建自定义Moshi适配器来处理这个问题?如果它返回表示对象的id,我想创建一个仅填充了id且其余字段设置为null的对象。

我尝试这样创建自定义适配器:

class bAdapter {
    @FromJson
    fun fromJson(b: Any): B {
        return when (b) {
            is String -> B(b)
            else -> b as B
        }
    }
}

但是我遇到了错误

com.squareup.moshi.JsonDataException: java.lang.ClassCastException: com.squareup.moshi.LinkedHashTreeMap cannot be cast to com.example.B
1个回答

1
如果有人遇到相同的问题,我通过使用巧妙的@JsonQualifier注释解决了它,如下所示:
@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
internal annotation class ObjectString

class ObjectStringAdapter {
    @FromJson
    @ObjectString
    fun fromJson(id: String): Object {
        return Object(id)
    }

    @ToJson
    fun toJson(@ObjectString obj: Object): String {
        return obj.toString()
    }
}

class ObjectAdapter {
    @FromJson
    fun fromJson(jsonReader: JsonReader, @ObjectString stringAdapter: JsonAdapter<Object>, defaultAdapter: JsonAdapter<Object>): Object {
        return when (JsonReader.Token.STRING) {
            jsonReader.peek() -> {
                stringAdapter.fromJson(jsonReader)
            }
            else -> {
                defaultAdapter.fromJson(jsonReader)
            }
        }!!
    }
}

其中 Object 是您的类。

基本上创建了两个适配器,一个用于字符串,另一个用于对象,并使用 jsonReader.peek() 来查看值并在运行时确定使用哪个,具体取决于类型。

参考链接:Moshi LocalDateTime adapter with multiple format


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接