如何将 JSON 反序列化为具有已知必填字段但可以具有多个未知字段的 Java class?

How can I deserialize a JSON to a Java class which has known mandatory fields, but can have several unknown fields?

我有一个输入 JSON,其中包含我确定的字段。但是,我需要灵活地添加几个额外的字段。我不知道额外字段的名称,但我必须处理它。

我正在考虑添加一个包含所有额外字段的 MaP 字段,但输入未映射到此字段。

我想反序列化 Dropwizard 端点中的 JSON。

杰克逊有办法吗?

示例:

JSON 负载 1:

{
  "first_name": "John",
  "last_name": "Doe",
  "date_of_birth": "01/01/1990",
  "postcode": "1234"
}

JSON 负载 2:

{
  "first_name": "Alice",
  "last_name": "Havee",
  "phone_no": 012345678,
  "passport_no": "AB 123456"
}

稍后 JSON 负载 3 甚至可以有不同的字段。

Java DTO:

public class PersonDTO {

    // mandatory field
    private String firstName;

    // mandatory field
    private String lastName;

    // Unknown optional fields?

    // No args constructor
    // Getters
    // Setters
}

您可以使用 JsonAnySetter 注释:

class PersonDTO {

    @JsonProperty("first_name")
    private String firstName;

    @JsonProperty("last_name")
    private String lastName;

    private Map<String, String> extras = new HashMap<>();

    @JsonAnySetter
    public void setExtras(String name, String value) {
        this.extras.put(name, value);
    }

    // No args constructor
    // Getters
    // Setters
}

另请参阅:

如果您使用 Jackson,您可以做几件事:-

  1. 您可以使用@JsonAnyGetter 和@JsonAnySetter 注释并将您的class 创建为:-

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;

import java.util.HashMap;
import java.util.Map;

public class PersonDTO {

    // mandatory field
    private String firstName;

    // mandatory field
    private String lastName;

    // Unknown optional fields?
    // Capture all other fields that Jackson do not match other members
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

    // No args constructor
    // Getters
    // Setters
}
  1. 如果您不想在 PersonDTO 中使用未知字段,那么您可以使用 class 级别的注释 @JsonIgnoreProperties 忽略未知属性,例如
@JsonIgnoreProperties(ignoreUnknown = true)
public class PersonDTO { //TODO:- }
  1. ObjectMapper 也可以配置为忽略未知数,例如:-
new ObjectMapper()
  .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)