当对象变量设置为 Private 时,Jackson ObjectMapper 返回 null

key*_*ger 6 java jackson jackson-databind

我得到了这个转义的 JSON

"{\"UniqueId\":[],\"CustomerOffers\":{},\"Success\":false,\"ErrorMessages\":[\"Test Message\"],\"ErrorType\":\"GeneralError\"}"
Run Code Online (Sandbox Code Playgroud)

我需要使用 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'
Run Code Online (Sandbox Code Playgroud)

我创建了该类:

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
}
Run Code Online (Sandbox Code Playgroud)

然后我创建了转换它的方法

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

无论 Data 类中的哪个变量设置为 public,当the corresponding value我调用 getters 时我都会得到。无论 Data 类中的哪个变量设置为 private,当null我调用 getters 时我都会得到。

Getter 和 Setter 始终是公共的。

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

bur*_*ete 9

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

当你创建 fields 时private,你迫使 Jackson 使用 setter,而上述冲突使得无法正确反序列化对象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
}
Run Code Online (Sandbox Code Playgroud)

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

Get success false
Get uniqueID []
Run Code Online (Sandbox Code Playgroud)

  • 当您这样做时,您应该修复名称以遵循 Java 命名约定,该约定规定字段名称应以小写字母开头。 (2认同)

Tim*_*sen 5

默认情况下,Jackson 将仅尝试序列化类Data(或您尝试序列化/反序列化的任何类)上的公共字段。但是,您可以配置ObjectMapper为允许它序列化所有字段,无论可见性如何:

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Data data = mapper.readValue(newJSON, Data.class);
Run Code Online (Sandbox Code Playgroud)

请参阅此处此处了解更多信息。