即使存在默认构造函数,也无法从对象值反序列化(没有委托或基于属性的创建者)。

43

我有一个类看起来像这样:

class MyClass {
    private byte[] payload;

    public MyClass(){}

    @JsonCreator
    public MyClass(@JsonProperty("payload") final byte[] payload) {
        this.payload = payload;
    }

    public byte[] getPayload() {
        return this.payload;
    }

}

我正在使用Jackson进行序列化和反序列化。序列化运行良好,但在反序列化期间,我收到了以下错误消息 -

Cannot construct instance of `mypackage.MyClass` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

我在网上阅读有关这个问题的文章时,看到多篇文章建议添加默认构造函数或带有 @JsonCreator 注解的构造函数。我尝试添加了两者,但仍然遇到这个异常。我错过了什么?


2
我使用Jackson 2.9.7进行了如下的测试,反序列化也正常工作。 - haba713
你还需要为每个字段设置setter方法。 - Om Gupta
7个回答

24

编辑:

我刚刚找到了一个更好的解决方案,将ParanamerModule添加到ObjectMapper中即可:

mapper.registerModule(new ParanamerModule());

Maven:

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-paranamer</artifactId>
    <version>${jackson.version}</version>
</dependency>
ParameterNamesModule的优势似乎在于类不需要使用-parameters参数进行编译。

END EDIT


我尝试使用Jackson 2.9.9反序列化这个简单的POJO,遇到了相同的异常,添加一个默认构造函数解决了问题:

POJO:

public class Operator {

    private String operator;

    public Operator(String operator) {
        this.operator = operator;
    }

    public String getOperator() {
        return operator;
    }
}

ObjectMapper和序列化/反序列化:

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
mapper.setVisibility(PropertyAccessor.CREATOR, Visibility.ANY);

String value = mapper.writeValueAsString(new Operator("test"));
Operator result = mapper.readValue(value, Operator.class);

JSON:

{"operator":"test"}

异常:

com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Cannot construct instance of `...Operator` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"operator":"test"}"; line: 1, column: 2]

解决方案(带有默认构造函数的POJO):

public class Operator {

    private String operator;

    private Operator() {
    }

    public Operator(String operator) {
        this();
        this.operator = operator;
    }

    public String getOperator() {
        return operator;
    }
}

1
添加paranamer模块并不能解决jackson无法创建对象的问题,原因是缺少无参构造函数。已经使用paranamer 2.12.2进行了测试。 - carlos palma
4
由于Jackson的原因,您的解决方案禁止使用最终属性。嗯。 - mjs
如果这个类是一个第三方API,你无法更改它,那会发生什么? - Pascoal Eddy Bayonne

16

我遇到了同样的问题。我的问题是因为我使用了错误的JsonCreator类型。我错误地使用了org.codehaus.jackson.annotate.JsonCreator,但应该使用com.fasterxml.jackson.annotation.JsonCreator


12

8
在您的子类对象中添加默认构造函数:
public NameOfClass() {
    super();
}

3
@Data (which adds @RequiredArgsConstructor) indeed wasn't sufficient. I had to make the property non-final and add a @NoArgsConstructor - lilalinux

4
我看到了这个序列化和反序列化的kotlin数据类。我所需要做的就是为我的属性添加默认值,然后就可以读取这些值了。
data class DataClass(
  val key: String = "",    //  adding these default 
  val value: String = ""   //  values worked
)

没有= "",我会得到错误:
Cannot construct instance of `com.xxx.DataClass` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

0
我遇到了同样的问题,上面提供的解决方案都没有帮助。在发现调试版本可以正常工作后,我发现 R8 是罪魁祸首,因为它在发布版本中剥离了 Jackson 需要的一些代码。将 @JsonAutoDetect 添加到所有自定义类依赖项中解决了这个 bug。
@JsonAutoDetect
data class Car(
    val name: String // annotation not needed
    val engine: Engine // annotation needed
)
// @JsonAutoDetect is needed here
data class Engine(
    val name: String
)

0
我也遇到了同样的问题,在我的情况下,我正在使用Java消耗REST API语句...但是经过多次尝试,我发现需要添加默认构造函数,因为我已经声明了带有字段的构造函数。
public NameofClass() {
        super();
        // TODO Auto-generated constructor stub
    }

目前你的回答不太清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community
请通过清晰的代码片段来改进您的评论 - Dilip D

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