首页 > 解决方案 > 如何在 JSON 有效负载的单个字段中处理不同类型的值

问题描述

我遇到了一种情况,我必须支持现有的客户端,他们正在使用下面的有效负载作为 rest api,

{
  "firstName": "First name",
  "secondName": "Second name",
  "dateOfBirth": "01/12/2020",
  "profession": "Software Developer",
  "salary": 0,
  **"value": "value1"**
}

但现在根据要求,他们可以为值字段发送数组,如下所示:

{
  "firstName": "First name",
  "secondName": "Second name",
  "dateOfBirth": "01/12/2020",
  "profession": "Software Developer",
  "salary": 0,
  **"value": ["Value1", "value2", "Value3"]**
}

现有代码用于@RequestBody将其转换为PersonDTO person,该类还包含一个名为isMutliValue()&的方法getMultiValueFor(),这些方法基于逗号分割字符串,然后决定并从中返回值。但现在为了这个要求,我必须进行修改以检查客户端是发送值数组还是简单字符串。如果它是一个简单的字符串,那么不要基于逗号拆分它并简单地处理它,但如果它是一个数组,则将值从中取出并发送单个值。

public class PersonDTO {
    private String firstName;
    private String secondName;
    // Formats output date when this DTO is passed through JSON
    @JsonFormat(pattern = "dd/MM/yyyy")
    // Allows dd/MM/yyyy date to be passed into GET request in JSON
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Date dateOfBirth;

    private String profession;
    private BigDecimal salary;
    private String value;

    public PersonDTO(
            String firstName, String secondName, Date dateOfBirth, String profession, BigDecimal salary, String value) {
        this.firstName = firstName;
        this.secondName = secondName;
        this.dateOfBirth = dateOfBirth;
        this.profession = profession;
        this.salary = salary;
        this.value = value;
    }

    public PersonDTO() {}

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getSecondName() {
        return secondName;
    }

    public void setSecondName(String secondName) {
        this.secondName = secondName;
    }

    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public String getProfession() {
        return profession;
    }

    public void setProfession(String profession) {
        this.profession = profession;
    }

    public BigDecimal getSalary() {
        return salary;
    }

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public boolean isMultiValued() {
        return value.split(",").length > 1;
    }

    public String[] getMultiValues() {
        return value.split(",");
    }
    public String toString(){
        return "FirstName : " + firstName +" SecondName : "+ secondName +", Value : "+ value.toString();
    }

}

请帮帮我,我们如何在 json 有效负载的单个字段中处理不同类型的值

标签: javajsonspringspring-bootjava-8

解决方案


在这种情况下,您可以实现自定义反序列化。因此,为此目的,您应该定义一个PersonDTODeserializer扩展自JsonDeserializer和覆盖方法的deserialize方法。

public class PersonDTODeserializer extends JsonDeserializer {

@Override
public Object deserialize(JsonParser jsonParser, 
                       DeserializationContext deserializationContext) throws IOException {
    JsonNode node = jsonParser.getCodec().readTree(jsonParser);
    String name = node.get("firstName").textValue();
    String secondName = node.get("secondName").textValue();
    BigDecimal salary = node.get("salary").decimalValue();
    String value = "";
    JsonNode nodeValue = node.get("value");
    if (nodeValue.isArray()) {
        Iterator<JsonNode> nodeIterator = nodeValue.iterator();
        List<String> values = new ArrayList<>();
        while (nodeIterator.hasNext()) {
           values.add( nodeIterator.next().textValue());
        }
        value = String.join(",",values);

     } else if (nodeValue.isTextual()) {
        value = nodeValue.textValue();
     }

     return new PersonDTO(name, secondName, salary, value);
  }
}

并在PersonDTO课堂上使用。

@JsonDeserialize(using = PersonDTODeserializer.class)
public class PersonDTO {

   //other 
}

推荐阅读