33

我正在尝试使用 Jackson 将我的 POJO 读入/从 Json 读取/写入。截至目前,除了第 3 方课程外,我已经对其进行了配置并为我的课程工作。尝试读取 Json 时出现错误:

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type

经过一些快速的谷歌搜索,我的类似乎需要一个默认构造函数使用 annotations 覆盖默认构造函数。不幸的是,失败的类来自第 3 方库,并且该类没有默认构造函数,我显然无法覆盖代码。

所以我的问题是,我能做些什么呢,还是我运气不好?

谢谢。

4

2 回答 2

29

您可以利用Jackson 的 Mix-Ins 功能以及Creator 功能。Mix-Ins 功能减轻了对原始第三方代码进行注释的需要,Creator 功能提供了自定义实例创建的机制。

对于更多的自定义,编写自定义反序列化器并不太复杂。

于 2012-08-07T02:30:42.220 回答
0

一种方法是实现一个自定义JsonDeserializer来创建实例,用 注释该类型的字段@JsonDeserialize。这种方法相对于 mixins 的一个优点是它不需要修改ObjectMapper.

该类StdNodeBasedDeserializer允许从JsonNode表示值的映射到所需类型。

缺少构造函数的类型

public class ThirdPartyType {
    private String stringProperty;

    private int intProperty;

    private Object[] arrayProperty;

    public ThirdPartyType(String a, int b, Object[] c) {
        this.stringProperty = a;
        this.intProperty = b;
        this.arrayProperty = c;
    }
    
    // Getters and setters go here
}

自定义解串器

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdNodeBasedDeserializer;

import java.io.IOException;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.StreamSupport;

public class ThirdPartyTypeDeserializer 
        extends StdNodeBasedDeserializer<ThirdPartyType> {
    protected ThirdPartyTypeDeserializer() {
        super(ThirdPartyType.class);
    }

    @Override
    public ThirdPartyType convert(JsonNode root, DeserializationContext ctxt)
            throws IOException {
        return new ThirdPartyType(
                root.get("stringProperty").asText(null),
                root.get("intProperty").asInt(),
                StreamSupport.stream(
                        Spliterators.spliteratorUnknownSize(
                                root.get("arrayProperty").elements(),
                                Spliterator.ORDERED),
                        false).toArray());
    }
}

包含第三方类型的类型

public class EnclosingClass {
    @JsonDeserialize(using = ThirdPartyTypeDeserializer.class)
    private ThirdPartyType thirdPartyProperty;
    
    // Getters and setters go here
}

检索值

String json = "{\"thirdPartyProperty\": {"
        + "\"stringProperty\": \"A\", "
        + "\"intProperty\": 5, "
        + "\"arrayProperty\": [1, \"B\", false]"
        + "}}";
ObjectMapper objectMapper = new ObjectMapper();
EnclosingClass enclosingClass =
        objectMapper.readValue(json, EnclosingClass.class);
于 2021-09-04T02:23:35.930 回答