我正在使用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
最佳答案
如果有人遇到相同的问题,我可以使用漂亮的@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
是您的类(class)。基本上创建了两个适配器,一个用于字符串,一个用于对象,并使用jsonReader.peek()窥视该值,并在运行时根据类型确定使用哪个。
供参考:Moshi LocalDateTime adapter with multiple format