杰克逊用匿名类反序列化

时间:2015-02-09 20:19:41

标签: java json serialization jackson deserialization

我一直在寻找能够解决这个问题的事情,但到目前为止我还没有好运。

我的问题很简单:如何使用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);
}

在我得到异常之前,输出是:JSON = [" com.foo.test.JacksonTest $ 1",{" value":5}]:

线程中的异常" main" com.fasterxml.jackson.databind.JsonMappingException:无法将类com.foo.test.JacksonTest $ 1(类型为local / anonymous)反序列化为Bean

编辑为了澄清,Jackson和XStream都能够序列化该对象。但只有XStream似乎能够反序列化该对象。因此,这种情况可以起作用。

4 个答案:

答案 0 :(得分:7)

截至我写这篇文章的时候,杰克逊似乎没有正确地序列化内部类或匿名类。然而,其他包如XStream和Kryo​​也会这样做。

答案 1 :(得分:0)

问题不仅仅在于它是一个内部类(可能存在问题,也可能不存在问题,取决于实现是静态的还是非静态的),而且还包括没有包含类型信息 - 杰克逊看到的只是类型Interface1。要启用它,必须包含类型信息(“多态类型处理”),或者指定抽象类型和实现类之间的映射。

鉴于您使用的是匿名内部类,您可以通过启用所谓的“默认输入”来支持此用法(请参阅ObjectMapper javadocs for enableDefaultTyping()等)。 但是,如果您不想为所有非最终类型启用类型包含,您可能还需要实现特定策略。

要查看是否包含了类型ID,您可以使用默认选项之一启用默认输入,并查看正在生成的JSON:应该有一个额外的类型ID(当类名用作id时为“@class”属性)

答案 2 :(得分:0)

由于内部类没有默认的零参数构造函数(它们具有对外部/父类的隐藏引用),因此Jackson无法实例化它们。

您可以检查此link

答案 3 :(得分:0)

Jackson使用嵌套类对Java POJO进行通用JSON反序列化的现成代码片段:

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确保通用的JSON解析和填充。