【问题标题】:How to parse interfaces with GSON如何使用 GSON 解析接口
【发布时间】:2017-10-22 15:50:17
【问题描述】:

我有一个带有嵌套接口的接口模型。 每个接口也主要有 1 个具体的实现类,如:

public interface Book {

    String getTitle();
}

public class BookImpl implements Book {

    private String title;

    @Override
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

现在像这样解析 json:

gson.fromJson(json, Book.class);

由于它不知道实现类而不起作用。

所以我创建了一个自定义反序列化器,例如:

public class BookDeserializer implements JsonDeserializer<Book> {

    @Override
    public Book deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
        return context.deserialize(json, BookImpl.class);
    }
}

但我对模型中的每个接口都这样做。

这是正确的方法吗?创建如此简单的反序列化器?我觉得应该有更简单的方法。

与 Jackson 一样,我会创建一个自定义 Jackson Module 并注册类型映射,例如:

.addAbstractTypeMapping(Book.class, BookImpl.class)

GSON 也可以吗?

【问题讨论】:

    标签: java json jackson gson


    【解决方案1】:

    您可以使用JsonDeserializer的通用版本

    public static class MyDeserializer implements JsonDeserializer {
        private Class<?> implClass;
    
        public MyDeserializer(Class<?> c) {
            implClass = c;
        }
    
        @Override
        public Object deserialize(JsonElement json, Type typeOfT, 
                JsonDeserializationContext context) throws JsonParseException {
            return context.deserialize(json, implClass);
        }
    }
    

    然后像在杰克逊一样用一行注册它

    builder.registerTypeAdapter(A.class, new MyDeserializer(AImpl.class));
    builder.registerTypeAdapter(B.class, new MyDeserializer(BImpl.class));
    

    或者像使用 lambda 一样

    builder.registerTypeAdapter(G.class, (JsonDeserializer) (json, typeOfT, context)
                    -> context.deserialize(json, H.class));
    

    【讨论】:

    • 是的,自定义通用反序列化器是一个不错的选择。我只是想知道为什么已经没有类似的东西了。这就是为什么我认为我忽略了一些东西。
    • @MarcelOverdijk 实际上根据我的经验,这很常见。 Jackson 是一个更复杂且功能丰富的框架。这是nice list 但在这种情况下,在我看来,杰克逊addAbstractTypeMapping 只是addDeserializer/addSerializer 的语法糖。它只是builder.registerTypeAdapter(A.class, new Gson().getAdapter(AImpl.class)); 的懒惰版本。而且我实际上认为 gson 具有更酷的功能 registerTypeHierarchyAdapter 为每个实现设置单个适配器
    • 好的谢谢,我也会去registerTypeHierarchyAdapter看看。
    猜你喜欢
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 2016-08-25
    • 2015-07-10
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多