首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Gson RuntimeTypeAdapterFactory进行宽大=真设置

使用Gson RuntimeTypeAdapterFactory进行宽大=真设置
EN

Stack Overflow用户
提问于 2020-01-15 16:50:21
回答 1查看 805关注 0票数 4

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

现在,我们希望使用RuntimeTypeAdapterFactory类从gson中删除一些样板代码。刚才描述的行为不再适用于这里,我们得到了信息

java.lang.NumberFormatException: JSON禁止NaN和无穷大: NaN

它应该被忽略,因为通常从gson设置的lenient选项。

考虑这个小例子:

代码语言:javascript
复制
class Base
{
   String type;
   double malformedField;
}

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

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

这是我们用来创建子类和反序列化的设置:

代码语言:javascript
复制
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.TypeAdapterfromJsonTree方法,在该方法中,我们创建了一个新的JsonTreeReader,而不可能更改lenient选项。

代码语言:javascript
复制
public final T fromJsonTree(JsonElement jsonTree) {
    try {
        JsonReader jsonReader = new JsonTreeReader(jsonTree);
        return read(jsonReader);
    } catch (IOException e) {
        throw new JsonIOException(e);
    }
}

我尝试通过调试手动将其设置为true,这似乎像预期的那样工作(没有指定类型的NumberFormatException和object被正确反序列化)。

现在的问题是:关于为什么我们不能在这里使用lenient选项,我缺少什么东西吗?乍一看,这似乎是来自gson的一个bug,但我不确定。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-16 00:05:52

由于gson-extras类来自核心库,所以它并不完全是一个bug。我建议再注册一个TypeAdapterFactory,并对所有JsonReader实例强制使用lenient

代码语言:javascript
复制
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);
            }
        };
    }
}

用法:

代码语言:javascript
复制
Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(adapterFactory)
        .registerTypeAdapterFactory(new AlwaysLenientTypeAdapterFactory())
        .create();

另请参阅:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59756092

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档