Jackson 使用匿名类进行反序列化

问题描述 投票:0回答:4

我一整天都在寻找可以回答这个问题的东西,但到目前为止我还没有太多运气。

我的问题很简单:如何使用 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(本地/匿名类型)反序列化为Bean

编辑 澄清一下,Jackson 和 XStream 都能够序列化对象。但似乎只有 XStream 能够将对象反序列化回来。所以这个场景可以实现。

java json serialization jackson deserialization
4个回答
14
投票

在我写这篇文章时,Jackson 似乎没有正确序列化内部类或匿名类。但其他软件包(例如 XStream 和 Kryo)却可以。


2
投票

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

您可以查看此链接


0
投票

问题不仅仅在于它是一个内部类(这可能有问题也可能没有问题,具体取决于实现是静态还是非静态),而且还在于没有包含类型信息——Jackson 看到的只是类型

Interface1 
。为了能够读回它,必须包含类型信息(“多态类型处理”),或者指定抽象类型和实现类之间的映射。

假设您使用的是匿名内部类,您将能够通过启用所谓的“默认类型”来支持这种用法(请参阅

ObjectMapper
javadocs 了解
enableDefaultTyping()
等)。 但如果您不想为所有非最终类型启用类型包含,您可能还需要实施特定策略。

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


0
投票

使用嵌套类通过 Jackson 将通用 JSON 反序列化为 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
确保通用的 JSON 解析和填充。

© www.soinside.com 2019 - 2024. All rights reserved.