gpt4 book ai didi

java - 使用 Retrofit GsonConverterFactory 反序列化 false 或对象的 json

转载 作者:行者123 更新时间:2023-12-02 02:55:07 24 4
gpt4 key购买 nike

我正在使用返回 json 的服务器。其中一个元素要么是一个对象,要么是 false - 如果它不存在。我知道这是服务器响应的非常糟糕的实现,并且有很多这样的情况,但这就是我必须处理的。我该如何处理这种情况?如果有一个对象,我成功反序列化它,如果没有 - 我收到错误 - EXPECTED OBJECT FOUND 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完成。

非常感谢。

最佳答案

我假设您有一个类似于以下映射的顶级映射,并且已为 Gson 配置了您的 Retrofit 实例:

final class Response {

@SerializedName("progress")
@JsonAdapter(FalseAsNullTypeAdapterFactory.class)
final Progress progress = null;

}

final class Progress {

final String foo = null;

}

请注意,progress 属性使用 @JsonAdapter 注释进行注释:我们假设这是 progress 属性可以使用的唯一位置是一个 boolean 值(如果您有很多这样的地方,您可以使用此注释来注释每个字段,或者通过 GsonBuilder 来注释每个字段;如果是 .registerTypeAdapterFactory() 工厂必须检查已知类型,以免“拦截”所有类型。

现在,这是一个类型适配器工厂来处理您的问题:

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}

输出如下:

bar
null

关于java - 使用 Retrofit GsonConverterFactory 反序列化 false 或对象的 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43231983/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com