【问题标题】:Deserializing a Generic Type with Jackson使用 Jackson 反序列化泛型类型
【发布时间】:2012-10-18 14:24:38
【问题描述】:

我正在尝试创建一个使用 Jackson 反序列化 POJO 的类。

看起来像这样……

public class DeserialiserImp<T> implements Deserialiser<T> {

        protected ObjectMapper objectMapper = new ObjectMapper();

        @Override
        public T get(String content, Class clazz) throws IOException {
            return (T) objectMapper.readValue(content, clazz);
        }

        @Override
        public List<T> getList(String content, Class clazz) throws IOException {
            return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, clazz));
        }

    }

我有 2 个关于此实现的问题。

首先是我将类类型传递给方法,以便对象映射器知道应该反序列化的类型。有没有更好的使用泛型的方法?

此外,在 get 方法中,我将从 objectMapper 返回的对象转换为 T。这似乎特别讨厌,因为我必须在此处转换 T,然后我还必须从方法中转换对象类型,即调用它。

我在这个项目中使用 Roboguice,所以如果我可以通过注入更改类型然后注释我需要它返回的 Generic 类型的对象,那就太好了。我读到了TypeLiteral 并想知道它是否可以解决这个问题?

【问题讨论】:

标签: java android jackson guice roboguice


【解决方案1】:

所以我想我最终想通了。如果您发现我所做的事情有问题,请发表评论。

接口是这样定义的……

public interface Deserialiser<T> {

    T get(String content) throws IOException;

    List<T> getList(String content) throws IOException;
}

接口的实现是这样的……

public class DeserialiserImp<T> implements Deserialiser<T> {

    private ObjectMapper objectMapper = new ObjectMapper();
    private final Class<T> klass;

    @Inject
    public DeserialiserImp(TypeLiteral<T> type){
        this.klass = (Class<T>) type.getRawType();
    }

    @Override
    public T get(String content) throws IOException {
        return objectMapper.readValue(content, klass);
    }

    @Override
    public List<T> getList(String content) throws IOException {
        return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, klass));
    }

}

我像这样绑定 2..

    bind(new TypeLiteral<Deserialiser<User>>(){}).annotatedWith(Names.named("user")).to(new TypeLiteral<DeserialiserImp<User>>(){});

那么我需要做的就是使用它......

@Inject
@Named("user")
private Deserialiser<User> deserialiserImp;

public void test(String userString) {
    User user = deserialiserImp.get(UserString);
}

如果类作为抽象类在 DAO 对象中使用,这种模式也可以很好地工作

This 文章帮了我

【讨论】:

    【解决方案2】:

    首先是我将类类型传递给方法,所以 objectmapper 知道应该反序列化的类型。有没有更好的 使用泛型的方式?

    很遗憾没有,这是因为类型擦除。

    另外,在 get 方法中,我正在转换从 objectMapper 到 T。这似乎是我做的特别讨厌的方式 必须在这里转换 T 然后我还必须从 调用它的方法。

    改为这样做:

    @Override
    public T get(String content, Class<T> clazz) throws IOException {
        return objectMapper.readValue(content, clazz);
    }
    

    我在这个项目中使用 Roboguice,所以如果可以的话会很好 通过注入更改类型,然后注释对象 我需要它返回的通用类型。我阅读了关于 TypeLiteral 和 想知道它是否可以解决这个问题?

    我不太明白你想达到什么目标,但既然你无论如何都需要通过课程,那还有可能吗?

    【讨论】:

    • 我关于使用 TypeLiteral 的观点来自这个问题stackoverflow.com/questions/3370641/… 它说“这里使用的技巧是泛型超类型的签名存储在子类中,因此不会被擦除。”我希望不要传入类型。
    • 好的,我明白了。我在这里看不到任何实用的解决方案,您需要将类型存储在某处(普通的 Class 对象作为字段,使用 TypeLiteral 等......)以在运行时检索它。我不认为每次传递类型都是一个主要问题,因为所有解组库都需要它。不过,我很想看看另一种方法。
    • 好吧,我正在努力使代码更简洁。目前我在实例化反序列化器Imp时将类型作为泛型传递,我必须将类传递给方法,然后我还需要转换我收到的对象。所以这是我引用类型的 3 次。看起来很乱
    • 我指的是别的东西,但我意识到我误解了一些东西。谢谢
    • 我喜欢。我不知道 TypeLiteral 类型会自动注入。干净整洁。
    猜你喜欢
    • 2012-07-24
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 2019-04-29
    • 2014-04-05
    • 1970-01-01
    相关资源
    最近更新 更多