我正在尝试使用reddit JSON API。有些帖子数据对象包含一个名为edited的字段,如果帖子没有被编辑,则可能包含布尔值false,如果帖子被编辑,则可能包含时间戳int。
有时是布尔值:
{
"edited": false,
"title": "Title 1"
}
有时候是一个int:
{
"edited": 1234567890,
"title": "Title 2"
}
当试图解析POJO将字段设置为int的JSON时,我收到一个错误:JsonDataException:期望一个int但是BOOLEAN ...
我如何使用Moshi来解决这个问题?
答案 0 :(得分:2)
我也遇到了类似的问题,其中我的字段有时是布尔值,有时是整数。我希望他们永远是整数。这是我用Moshi和Kotlin解决的方法:
@JsonQualifier
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION)
annotation class ForceToInt
internal class ForceToIntJsonAdapter {
@ToJson
fun toJson(@ForceToInt i: Int): Int {
return i
}
@FromJson
@ForceToInt
fun fromJson(reader: JsonReader): Int {
return when (reader.peek()) {
JsonReader.Token.NUMBER -> reader.nextInt()
JsonReader.Token.BOOLEAN -> if (reader.nextBoolean()) 1 else 0
else -> {
reader.skipValue() // or throw
0
}
}
}
}
@JsonClass(generateAdapter = true)
data class Discovery(
@Json(name = "id") val id: String = -1,
@ForceToInt @Json(name = "thanked") val thanked: Int = 0
)
答案 1 :(得分:1)
简单的方法可能是使您的Java edited
字段成为Object类型。
性能,错误捕获和应用程序使用的更好方法是使用自定义JsonAdapter。
示例(根据需要进行编辑):
public final class Foo {
public final boolean edited;
public final int editedNumber;
public final String title;
public static final Object JSON_ADAPTER = new Object() {
final JsonReader.Options options = JsonReader.Options.of("edited", "title");
@FromJson Foo fromJson(JsonReader reader) throws IOException {
reader.beginObject();
boolean edited = true;
int editedNumber = -1;
String title = "";
while (reader.hasNext()) {
switch (reader.selectName(options)) {
case 0:
if (reader.peek() == JsonReader.Token.BOOLEAN) {
edited = reader.nextBoolean();
} else {
editedNumber = reader.nextInt();
}
break;
case 1:
title = reader.nextString();
break;
case -1:
reader.nextName();
reader.skipValue();
default:
throw new AssertionError();
}
}
reader.endObject();
return new Foo(edited, editedNumber, title);
}
@ToJson void toJson(JsonWriter writer, Foo value) throws IOException {
writer.beginObject();
writer.name("edited");
if (value.edited) {
writer.value(value.editedNumber);
} else {
writer.value(false);
}
writer.name("title");
writer.value(value.title);
writer.endObject();
}
};
Foo(boolean edited, int editedNumber, String title) {
this.edited = edited;
this.editedNumber = editedNumber;
this.title = title;
}
}
不要忘记在Moshi实例上注册适配器。
Moshi moshi = new Moshi.Builder().add(Foo.JSON_ADAPTER).build();
JsonAdapter<Foo> fooAdapter = moshi.adapter(Foo.class);