java - Jackson DeSerializer for Class<?扩展 Foo>

标签 java serialization jackson deserialization

我想要一个用于类文字的序列化器和反序列化器。它应该从/映射到 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<?> 调用此反序列化器.但我只是想让它被调用 Class<? extends Foo> .

顺便说一句:我想将其注册为全局反序列化器。我不想使用@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);

最佳答案

由于 Type Erasure,您尝试实现的目标似乎是不可能的,确实在运行时你的类 MyDeserializer被视为 JsonDeserializer<Class>和你的领域fooType只是类型 Class不是类型Class<? extends Foo>这就是为什么每个 Class<?> 都会调用您的解串器的原因.

在您的情况下,最好的解决方案是注释类型为 Class<? extends Foo> 的字段与 @JsonDeserialize(using = MyDeserializer.class)为了在运行时指示要使用的反序列化器,但由于您不想这样做,作为解决方法,假设在给定的类中,当您具有 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 
    }
}

关于java - Jackson DeSerializer for Class<?扩展 Foo>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41977574/

相关文章:

java - 如何从行值创建新列

java - 检测数组中的重复项

django:断言错误 `create()`没有返回对象实例

c# - 将空 XML 元素反序列化为 Guid.Empty

在 Applet 中执行操作后 Java JDBC 连接丢失

java - 此 portlet 无法访问路径/WEB-INF/jsp/newportlet/view.jsp

c# - 我如何判断一个类是否可以序列化?

java如何在类之间共享字段和方法

java - 尝试设置旧版 Java Spring 启动应用程序时出现导入 com.fasterxml.jackson 无法解析错误

java - 向字段添加冗余的@JsonProperty值注释是否会提高反序列化性能?