没有默认构造函数的杰克逊第 3 方类

Posted

技术标签:

【中文标题】没有默认构造函数的杰克逊第 3 方类【英文标题】:Jackson 3rd Party Class With No Default Constructor 【发布时间】:2012-08-04 00:00:07 【问题描述】:

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

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

经过几次快速的谷歌搜索后,我的班级似乎需要default constructor 或override the default constructor with annotations。不幸的是,失败的类来自第 3 方库,并且该类没有默认构造函数,我显然无法覆盖代码。

所以我的问题是,对此我有什么办法吗?还是我运气不好?

谢谢。

【问题讨论】:

您可以使用 BCEL、ASM 或类似的东西来设计具有构造函数的新版本的 3rd 方类文件。 【参考方案1】:

您可以使用Jackson's Mix-Ins feature,再加上the Creator feature。 Mix-Ins 功能减轻了对原始第三方代码进行注释的需要,Creator 功能提供了一种自定义实例创建机制。

对于更多的自定义,写a custom deserializer 并不复杂。

【讨论】:

这些链接适用于 Jackson 1。对于 Jackson 2,您可以将混音直接添加到 objectMapperobjectMapper.addMixInAnnotations(target, mixinSource) (source) 他是对的,我使用 mixin 方法反序列化了一个 android.location.Location 类型的字段,顺便说一下,它没有默认构造函数(而且我无法控制类/第三方)。序列化没问题,但反序列化时出现非默认构造函数异常。我从 Location 扩展了一个 mixin 类,并使用 JsonCreator 注释来实现一个使用特定字段的构造函数。工作就像一个魅力,感谢您向我展示@Programmer Bruce 的方式 查看这里以获得更多帮助:***.com/questions/30080217/… 以上已被弃用并再次更改为“流利”API:objectMapper.addMixIn(Target.class, MixIn.class);【参考方案2】:

一种方法是实现自定义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);

【讨论】:

以上是关于没有默认构造函数的杰克逊第 3 方类的主要内容,如果未能解决你的问题,请参考以下文章

龙目岛没有创建默认构造函数导致杰克逊数据绑定失败[重复]

杰克逊错误:没有适合简单类的构造函数

杰克逊没有为 android.graphics.Bitmap 找到合适的构造函数

杰克逊不能用一个参数构造函数构造实例

第19课 - 对象的构造(下)

构造函数