gpt4 book ai didi

java - 使用 Gson RuntimeTypeAdapterFactory 和 lenient = true 设置

转载 作者:行者123 更新时间:2023-12-03 22:54:08 31 4
gpt4 key购买 nike

我们摄取的 API 返回一些格式错误的 JSON(特别是 Double.NaN 被序列化为带有“NaN”的 String)。
允许此 gson 始终设置 lenient为 true 并正确地将其序列化回 Double.NaN .

现在,我们想使用 RuntimeTypeAdapterFactory来自 的类(class)gson-extras 删除一些样板代码。
刚才描述的行为在这里不再适用,我们得到了消息

java.lang.NumberFormatException: JSON forbids NaN and infinities: NaN



哪一个
由于 lenient 应该被忽略选项通常从 gson 设置。

考虑这个小例子:
class Base
{
String type;
double malformedField;
}

class A extends Base{}
class B extends Base{}

我们使用 type字段以确定我们想要哪个子类,因为当然否则我们无法推断出正确的类型。

这是我们用来创建子类和反序列化的设置:
RuntimeTypeAdapterFactory<Base> adapterFactory = RuntimeTypeAdapterFactory.of(Base.class, "type", true)
.registerSubtype(A.class, "A")
.registerSubtype(B.class, "B");

Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(adapterFactory)
//.setLenient() // Has no effect at all
.create();

String json = "{\"type\":\"A\", \"malformedField\": \"NaN\"}";
Base a = gson.fromJson(json, Base.class); // throws said Exception

RuntimeTypeAdapterFactory 中实现:

检查来自 RuntimeTypeAdapterFactory 的代码后我注意到 lenient选项永远不会设置为 true,因为我们调用了 fromJsonTree com.google.gson.TypeAdapter的方法,我们在其中创建了一个新的 JsonTreeReader无法更改 lenient选项。
public final T fromJsonTree(JsonElement jsonTree) {
try {
JsonReader jsonReader = new JsonTreeReader(jsonTree);
return read(jsonReader);
} catch (IOException e) {
throw new JsonIOException(e);
}
}

我试图通过调试手动将其设置为 true这似乎按预期工作(不 NumberFormatException并且对象使用指定的类型正确反序列化)。

现在的问题是:关于为什么我们不能使用 lenient,我有什么遗漏吗?选项在这里?乍一看,这似乎是来自 的错误。 gson-extras 但我不确定。

最佳答案

这不是来自 gson-extras 的错误自 com.google.gson.TypeAdapter类来自核心库。我建议多注册一个 TypeAdapterFactory和力lenient所有 JsonReader实例:

class AlwaysLenientTypeAdapterFactory implements TypeAdapterFactory {

public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
return createCustomTypeAdapter(delegate);
}

private <T> TypeAdapter<T> createCustomTypeAdapter(TypeAdapter<T> delegate) {
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}

@Override
public T read(JsonReader in) throws IOException {
in.setLenient(true);
return delegate.read(in);
}
};
}
}

用法:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(adapterFactory)
.registerTypeAdapterFactory(new AlwaysLenientTypeAdapterFactory())
.create();

也可以看看:
  • Is there an easy way to make Gson skip a field if there's an errordeserializing it?
  • 关于java - 使用 Gson RuntimeTypeAdapterFactory 和 lenient = true 设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59756092/

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