繁体   English   中英

如果没有默认构造函数,为什么将JSON编码的字符串转换为Java类实例失败?

[英]Why does conversion of JSON encoded string to a Java class instance fail without default constructor?

我有以下代码将T类型的实例编码为String 然后尝试将编码后的字符串转换回类T的实例。

package com.ncr.nep.messaging.notifications.tests;

import java.io.IOException;
import java.io.Serializable;    
import com.fasterxml.jackson.databind.ObjectMapper;    
import io.vertx.core.json.JsonObject;

class T implements Serializable {
    private String channel;

    //public T() { }
    public T(String channel) {
        super();
        this.channel = channel;
    }
    public String getChannel() {
        return channel;
    }
}
public class Test {
    public static void main(String[] args) {
        T t = new T("abc");
        String enc = JsonObject.mapFrom(t).encode();
        System.out.println(enc); //prints: {"channel":"abc"}
        //now back from String to T
        try {
            t = new ObjectMapper().readValue(enc,T.class);
            System.out.println(t.getChannel());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

readValue方法调用将引发以下异常:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.ncr.nep.messaging.notifications.tests.T: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
 at [Source: {"channel":"abc"}; line: 1, column: 2]

取消注释默认构造函数可解决此问题并生成正确的T实例。

我发现很难想象这个实用工具类ObjectMapper的设计者对他们的客户施加了如此大的约束。
请注意,我可能已经声明通道为最终通道,在这种情况下,要解决此问题,不仅需要添加默认构造函数,而且还需要更改所有成员-而不是“最终” ...

所以我的问题是这样的:
如果类T的设计器明确禁止默认构造函数,该怎么办。 还有什么可以做的吗? 有注释可以解决问题吗?

你可以尝试用注释的构造@JsonCreator并与参数@JsonProperty这样

@JsonCreator
public T(@JsonProperty("channel") String channel) {
    super();
    this.channel = channel;
}

问题是天气MOXy或Jackson都需要一种创建对象的方法。 您只提供T.class 他们应该如何知道如何使用构造函数。 就您而言,这可能很简单,但对于

public T(String a, String b) {..}

这将更加困难。 在这种情况下,您可以添加另一个约束,例如参数名需要与json属性名匹配。 我猜想这和默认构造器的缺点相同。

更新:我不知道描述的解决方案@ Link64,但是如果这样更好。 我不知道。 MOXy提供了XMLAdapter来创建对象。 例如,如果T类不受您控制。

JavaBeans模式要求:

它们是可序列化的,具有零参数构造函数,并允许使用getter和setter方法访问属性。

由于这种形式的Java类经常在许多框架中使用,因此用户应该期望这一要求。

“如果T的设计者禁止默认构造函数”的解决方案取决于特定的用例。 我通常会说这样的类不是bean,因此也不是一个很好的传输对象-您最好使用自己的传输对象,该对象遵循预期的格式并提供将其从目标类转换为目标类的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM