【发布时间】:2020-01-15 16:50:21
【问题描述】:
我们提取的 API 返回一些格式错误的 JSON(特别是 Double.NaN 被序列化为带有“NaN”的 String)。
要允许此 gson 始终将 lenient 设置为 true 并将其正确序列化回 Double.NaN。
现在,我们想使用 gson-extras 中的 RuntimeTypeAdapterFactory 类来删除一些样板代码。
刚才描述的行为在这里不再适用,我们得到消息
java.lang.NumberFormatException:JSON 禁止 NaN 和无穷大:NaN
哪个
由于通常从 gson 设置的 lenient 选项应该被忽略。
考虑这个小例子:
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,因为我们调用com.google.gson.TypeAdapter 的fromJsonTree 方法,其中我们创建了一个新的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 的错误,但我不确定。
【问题讨论】:
标签: java json polymorphism gson deserialization