【问题标题】:Jackson DeSerializer for Class<? extends Foo>类的杰克逊反序列化器<?扩展 Foo>
【发布时间】:2017-02-01 10:37:48
【问题描述】:

我想要一个用于类文字的序列化器和反序列化器。它应该从 / 映射到 JSON 字符串。它也应该适用于泛型类。

我尝试编写自定义反序列化器,但它处理所有类,而不仅仅是我想要的类:

public class MyDeserializer extends JsonDeserializer<Class<? extends Foo>> {
    public Class<? extends Foo> deserialize(JsonParser jp, DeserializationContext ctxt) 
        throws IOException, JsonProcessingException {

        String token = jp.getText();
        switch(token) {
            case "FOO": return Foo.class;
            case "BAR": return Bar.class;
        }
        return null;
    }
}

Jackson 将为每个Class&lt;?&gt; 调用此反序列化器。但我只是希望它被调用为Class&lt;? extends Foo&gt;

顺便说一句:我想将其注册为全局反序列化器。我不想想在任何地方都使用@JsonDeserialize

我怎样才能让它正常工作?

提前致谢。

编辑:更多代码

POJO:

public class MyPOJO {
    public Class<? extends Foo> fooType;
}

JSON:

{
    "fooType": "FOO"
}

ObjectMapper 用法:

MyPOJO pojo = new MyPOJO();
pojo.fooType = Foo.class;

ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(pojo);

【问题讨论】:

  • 能否请您为 Json POJO 添加代码并使用ObjectMapper
  • 添加了一些代码
  • 如果你不想使用@JsonDeserialize,你能不能只在需要的地方使用@JsonIgnore? (即瞬态&不可序列化)
  • @Shine:不。我应该可以拥有JsonDeserializer&lt;Class&lt;? extends Foo&gt;&gt;JsonDeserializer&lt;Class&lt;? extends AnotherClass&gt;&gt;。两者都必须适用于不同的课程。在使用JsonDeserializer&lt;Class&lt;? extends Foo&gt;&gt; 的那一刻,它会为每一种 类运行,即使是Class&lt;Object&gt;
  • 如果它不是Class&lt;? extends Foo&gt; 类型,而是任何其他类,你希望它做什么?

标签: java serialization jackson deserialization


【解决方案1】:

由于Type Erasure,您尝试实现的目标似乎是不可能的,实际上在运行时您的类MyDeserializer 被视为JsonDeserializer&lt;Class&gt;,而您的字段fooType 只是Class 类型而不是@ 类型987654326@ 这就是为什么每个Class&lt;?&gt; 都会调用你的反序列化器的原因。

在您的情况下,最好的解决方案是使用 @JsonDeserialize(using = MyDeserializer.class) 注释您的 Class&lt;? extends Foo&gt; 类型的字段,以便在运行时指示要使用的反序列化器,但由于您不想这样做,因此作为解决方法,假设在给定的类中,当您有 Class 类型的字段时,它们都将使用相同的反序列化器(自定义或默认),您可以简单地修改您的类 MyDeserializer 以首先检查当前的 bean 类以了解我们是否应该使用自定义反序列化器或默认的。

您可以将其注册为例如下一个:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("MyModule")
    .addDeserializer(Class.class, new MyDeserializer());
mapper.registerModule(module);

您的反序列化器的代码将是:

public class MyDeserializer extends JsonDeserializer<Class<?>>  {

    // The default deserializer for a property of type Class
    private final FromStringDeserializer.Std defaultDeserializer;

    public MyDeserializer() {
        // Set the default deserializer
        this.defaultDeserializer = FromStringDeserializer.findDeserializer(Class.class);
    }

    public Class<?> deserialize(JsonParser jp, DeserializationContext ctxt) 
        throws IOException, JsonProcessingException {
        // Check whether we should used the custom or default deserializer
        // based on the bean class
        if (accept(jp.getCurrentValue().getClass())) {
            // The custom deserializer
            String token = jp.getText();
            switch(token) {
                case "FOO": return Foo.class;
                case "BAR": return Bar.class;
            }
            return null;
        }
        // Call the default deserializer
        return (Class<?>) defaultDeserializer.deserialize(jp, ctxt);
    }

    // Returns true if this bean class has fields of type Class that must
    // be deserialized with the custom deserializer, false otherwise
    public boolean accept(Class<?> beanClass) {
        // Implement your logic here
        // You could for example have all the bean classes in a Set and 
        // check that the provided class is in the Set 
    }
}

【讨论】:

    猜你喜欢
    • 2016-10-23
    • 2016-11-11
    • 2015-04-07
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    相关资源
    最近更新 更多