我正在使用返回json的服务器。其中一个元素要么是对象要么是假的 - 它不存在。我知道服务器响应的实现很差,并且有很多这样的情况,但这是我必须要处理的。我该如何处理这种情况?如果有一个对象我成功反序列化它,如果没有 - 我得到错误 - 预期对象找到BOOLEAN。 更糟糕的是,我不知道将来我会在这个项目中遇到这种情况。 这是示例json:
{
"course": {
"id": "47902",
"course": "3844",
"group": "1825",
"teacher": "59502",
"table": "1447",
"client": "1",
"course_id": "3844",
"description": ""
},
"teacher": {
"id": "59502",
"post": "0",
"experience": "",
"dep_experience": "",
"rank": "0",
"online": "1458891283",
"departments": [
null
]
},
"depart": {
"id": "100",
"postcode": "",
"public": "1",
"alias": "",
"faculty": "97",
"client": "1"
},
"progress": false,
"files": [
{
"teacher": {
"id": "59502",
"code": "53bd7c21ad05b03e",
"photo": "1"
},
"files": [
{
"id": "0ffe41e5003ee5c0",
"owner": "59502",
"address": "0ffe41e5003ee5c0",
"type": "f",
"size": "0",
"time": "2015-07-10 14:39:15",
"data": ""
}
]
}
]
}
正如您所见,progress
在这里是假的。其他时候它是普通的对象,如depart
。反序列化由Retrofit 2完成。
非常感谢。
答案 0 :(得分:1)
我假设您有一个类似于以下内容的顶级映射,并为Retrofit
配置了Gson
个实例:
final class Response {
@SerializedName("progress")
@JsonAdapter(FalseAsNullTypeAdapterFactory.class)
final Progress progress = null;
}
final class Progress {
final String foo = null;
}
请注意,progress
属性是使用@JsonAdapter
注释注释的:我们假设这只是progress
属性可以是布尔值的地方(如果你有很多)像这样的地方,您可以使用此注释注释每个字段,或.registerTypeAdapter()
通过GsonBuilder
;如果是.registerTypeAdapterFactory()
,工厂必须检查已知类型,以便不#34}拦截"所有类型)。
现在,这是一个处理您的问题的类型适配器工厂:
final class FalseAsNullTypeAdapterFactory
implements TypeAdapterFactory {
// Let Gson instantiate it itself
private FalseAsNullTypeAdapterFactory() {
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
// Get a downstream parser (for simplicity: get the default parser for the given type)
final TypeAdapter<T> delegateTypeAdapter = gson.getDelegateAdapter(this, typeToken);
return new TypeAdapter<T>() {
@Override
public void write(final JsonWriter out, final T value) {
throw new UnsupportedOperationException();
}
@Override
public T read(final JsonReader in)
throws IOException {
// Peek whether the next JSON token is a boolean
if ( in.peek() == BOOLEAN ) {
// And take the this JSON token as a boolean value
// Is it true?
if ( in.nextBoolean() ) {
// Then it's not something we can handle -- probably a boolean field annotated with @JsonAdapter(FalseAsNullTypeAdapterFactory.class)?
throw new MalformedJsonException("Unexpected boolean marker: true");
}
// We're assuming it's null
return null;
}
// If it's not a boolean value, then we just delegate parsing to the original type adapter
return delegateTypeAdapter.read(in);
}
};
}
}
现在就测试一下:
try ( final Reader reader = getPackageResourceReader(Q43231983.class, "success.json") ) {
final Response response = gson.fromJson(reader, Response.class);
System.out.println(response.progress.foo);
}
try ( final Reader reader = getPackageResourceReader(Q43231983.class, "failure.json") ) {
final Response response = gson.fromJson(reader, Response.class);
System.out.println(response.progress);
}
给定资源是:
success.json
是{"progress":{"foo": "bar"}}
; failure.json
是{"progress":false}
。输出如下:
巴
null