没有默认构造函数的Jackson第三方类

34

我正在尝试使用Jackson将我的POJO(Java普通对象)读取/写入Json。目前为止,我已经将其配置并应用于我的类,但是对于一个第三方类,我还没有成功。当我尝试读取Json时,出现以下错误:

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

经过几次快速的谷歌搜索,我发现我的类需要一个默认构造函数或使用注释 覆盖默认构造函数。不幸的是,导致问题的类来自第三方库,该类没有默认构造函数,而且我显然不能覆盖代码。

所以我的问题是,我能做些什么还是只能认倒霉了?

谢谢。


您可以使用BCEL、ASM或类似工具来编写一个新版本的第三方类文件,该文件具有构造函数。 - jbranchaud
2个回答

29

4
这些链接是给Jackson 1用的。对于Jackson 2,你可以直接将Mix-in添加到objectMapper中,即objectMapper.addMixInAnnotations(target, mixinSource)来源)。 - kuporific
他是对的,我使用了mixin方法来反序列化类型为android.location.Location的字段,顺便说一下,该类型没有默认构造函数(而且我无法控制类/第三方)。序列化没有问题,但在反序列化时出现了非默认构造函数异常。我从Location扩展了一个mixin类,并使用JsonCreator注释实现了使用特定字段的构造函数。像魅力一样工作,感谢@Programmer Bruce向我展示了这条路。 - 1vand1ng0
点击此处获取更多帮助: https://stackoverflow.com/questions/30080217/json-deserialisation-using-jackson-no-suitable-constructor-found-for-type-pro - user64141
以上内容已被弃用并再次更改为“流畅”API:objectMapper.addMixIn(Target.class, MixIn.class); - jordanpg

1
一种方法是实现自定义 JsonDeserializer 来创建实例,并使用 @JsonDeserialize 注释类型的字段。与 mixins 等其他方法相比,这种方法的优点在于不需要修改 ObjectMapperStdNodeBasedDeserializer 类允许从代表值的 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
}

Retrieving the value

String json = "{\"thirdPartyProperty\": {"
        + "\"stringProperty\": \"A\", "
        + "\"intProperty\": 5, "
        + "\"arrayProperty\": [1, \"B\", false]"
        + "}}";
ObjectMapper objectMapper = new ObjectMapper();
EnclosingClass enclosingClass =
        objectMapper.readValue(json, EnclosingClass.class);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接