当Object变量设置为Private

时间:2019-09-26 05:45:37

标签: java jackson jackson-databind

我得到了这个转义的JSON

"{\"UniqueId\":[],\"CustomerOffers\":{},\"Success\":false,\"ErrorMessages\":[\"Test Message\"],\"ErrorType\":\"GeneralError\"}"

,我需要使用Jackson将其转换为Java对象。

// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'

我创建了课程:

public class Data {

    private List<UUID> UniqueId;
    private Map<Integer, List<Integer>> CustomerOffers;
    private Boolean Success;
    private List<String> ErrorMessages;
    private String ErrorType;

    // getter, setters
}

然后我创建了将其转换的方法

public class Deserializing {

    public void processing(String input) {

        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);



        String jsonInString = "\"{\"UniqueId\":[],\"CustomerOffers\":{},\"Success\":false,\"ErrorMessages\":[\"Test Message\"],\"ErrorType\":\"GeneralError\"}\"";
        String newJSON = org.apache.commons.lang3.StringEscapeUtils.unescapeJava(jsonInString);
        newJSON= newJSON.substring(1, jsonInString.length()-1);


            try {
            // JSON string to Java object
            Data data = mapper.readValue(newJSON, Data.class); 
            System.out.println(data);

            System.out.println("Get Success "+ data.getSuccess());  // return "false" if Data object is public ; null if private
            System.out.println("Get UniqueID " + data.getUniqueId()); // return [] if Data object is public ; null if private

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如果Data类中的任何变量设置为public,那么当我调用getter时,我都会得到the corresponding value。 无论Data类中的哪个变量设置为private,那么我在调用getter时都会得到null

字母和二传手总是公开的。

我想知道,如果ObjectMapper设置为私有对象,为什么不能映射该对象?我可以将其设置为公开,但这不是最佳实践。

4 个答案:

答案 0 :(得分:2)

问题在于,杰克逊将始终假设setSuccess()getSuccess()将用于success字段,而不是Success@JsonProperty需要支持以大写字母开头的JSON字段名称。 Java有一个约定,即类成员始终以小写字母开头,您可以使用此注释来实现这一点。

创建字段private时,您迫使Jackson使用设置器,并且上述冲突使得无法正确反序列化Data对象。

解决办法;

public class Data {

    @JsonProperty("UniqueId")
    private List<UUID> uniqueId;
    @JsonProperty("CustomerOffers")
    private Map<Integer, List<Integer>> customerOffers;
    @JsonProperty("Success")
    private Boolean success;
    @JsonProperty("ErrorMessages")
    private List<String> errorMessages;
    @JsonProperty("ErrorType")
    private String errorType;

    // getter&setters
}

然后您将看到正确反序列化为Java对象的值;

Get success false
Get uniqueID []

答案 1 :(得分:1)

默认情况下,Jackson只会尝试序列化from_name(...)类(或您要序列化/反序列化的任何类)上的公共字段。但是,您可以配置Data以允许其对所有字段进行序列化,而不考虑可见性:

ObjectMapper

有关更多信息,请参见herehere

答案 2 :(得分:1)

在JavaBeans规范(构造Java类属性的通用指南)中,属性定义为以小写字母(errorMessages)开头;访问器,因为它们有前缀,所以将其大写(getErrorMessages)。杰克逊默认使用属性名称,因此,当您拥有方法getErrorMessages时,它将查找具有键errorMessages的JSON属性。

最好的方法是更改​​JSON;我见过样式errorMessageserror_messages,但从未见过ErrorMessages。如果不能这样做,则可以将@JsonProperty应用于属性,以告诉Jackson在JSON中使用其他名称。

答案 3 :(得分:0)

此外,还有一点要注意:在这种情况下,如果Data类包含任何带有参数的构造函数,并且不包含空构造函数。这样,对象映射器将无法映射相应的对象。因此,在这种情况下,它也会返回null。