简体   繁体   English

Jackson 使用匿名类反序列化

[英]Jackson deserialization with anonymous classes

I have been searching all day for something that answers this, but I have not had a lot of luck thus far.我一整天都在寻找可以回答这个问题的东西,但到目前为止我的运气并不好。

My question is straightforward: how do I deserialize an anonymous object correctly using Jackson.我的问题很简单:如何使用 Jackson 正确反序列化匿名对象。

private interface Interface1
{
    int getValue();
}

public static void testAnonymousObject() throws IOException
{
    ObjectMapper mapper = new ObjectMapper();

    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
    mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
    mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

    Interface1 testObject = new Interface1()
    {
        private final int value = 5;

        @Override
        public int getValue()
        {
           return value;
        }
    };

    String json = mapper.writeValueAsString(testObject);
    System.out.println("JSON = " + json);

    Interface1 received = (Interface1) mapper.readValue(json, Object.class);
    System.out.println(received);
}

The output of this is: JSON = ["com.foo.test.JacksonTest$1",{"value":5}] before I get an exception:输出是: JSON = ["com.foo.test.JacksonTest$1",{"value":5}] 在我得到异常之前:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize Class com.foo.test.JacksonTest$1 (of type local/anonymous) as a Bean .线程“main”com.fasterxml.jackson.databind.JsonMappingException 中的异常:无法将类 com.foo.test.JacksonTest$1(本地/匿名类型)反序列化为 Bean

EDIT Just to clarify, both Jackson and XStream are able to serialize the object.编辑只是为了澄清,Jackson 和 XStream 都能够序列化对象。 But only XStream seems to be able to deserialize the object back.但似乎只有 XStream 能够反序列化对象。 So this scenario can be made to work.所以这个场景可以工作。

As of the time I am writing this, it seems that Jackson does not serialize inner classes or anonymous classes correctly.在我写这篇文章的时候,Jackson 似乎没有正确地序列化内部类或匿名类。 Other packages such as XStream and Kryo, do however.但是,其他软件包,例如 XStream 和 Kryo。

Because inner classes do not have a default zero argument constructor (they have a hidden reference to the outer/parent class) Jackson cannot instantiate them.因为内部类没有默认的零参数构造函数(它们具有对外部/父类的隐藏引用),所以 Jackson 无法实例化它们。

you can check this link你可以检查这个链接

Problem is not just about it being an inner class (which may or may not be problematic, depending on whether implementation is static or non-static), but also in that no type information is included -- all Jackson sees is type Interface1 .问题不仅在于它是一个内部类(这可能有问题,也可能没有问题,这取决于实现是静态的还是非静态的),还在于没有包含类型信息——杰克逊看到的只是类型Interface1 To enable reading it back it is necessary to either include type information ("polymorphic type handling"), or to specify mapping between abstract type and implementation class.为了能够读回它,必须包含类型信息(“多态类型处理”),或者指定抽象类型和实现类之间的映射。

Given that you are using an anonymous inner class, you would be able to support this usage by enabled so-called "default typing" (see ObjectMapper javadocs for enableDefaultTyping() or such).鉴于您使用的是匿名内部类,您将能够通过启用所谓的“默认类型”来支持这种用法(请参阅ObjectMapper javadocs for enableDefaultTyping()等)。 But you may also need to implement specific strategy, if you do not want to enable type inclusion for all non-final types.但是,如果您不想为所有非最终类型启用类型包含,您可能还需要实施特定策略。

To see whether type id is included you can enable default typing with one of default options and have a look at JSON being produced: there should be an additional type id ("@class" property when class name is used as id).要查看是否包含类型 id,您可以使用默认选项之一启用默认类型,并查看正在生成的 JSON:应该有一个额外的类型 id(当类名用作 id 时,“@class”属性)。

A ready-to-use code-snippet for a generic JSON-deserialization to a Java POJO with Jackson using nested classes:一个现成的代码片段,用于使用嵌套类将通用 JSON 反序列化为带有 Jackson 的 Java POJO:

static class MyJSON {

    private Map<String, Object> content = new HashMap<>();

    @JsonAnySetter
    public void setContent(String key, Object value) {
        content.put(key, value);
    }
}

String json = "{\"City\":\"Prague\"}";

try {

    MyPOJO myPOJO = objectMapper.readValue(json, MyPOJO.class);

    String jsonAttVal = myPOJO.content.get("City").toString();

    System.out.println(jsonAttVal);

} catch (IOException e) {
    e.printStackTrace();
}

@JsonAnySetter ensures a generic JSON-parsing and population. @JsonAnySetter确保通用的 JSON 解析和填充。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM