簡體   English   中英

如何使用 Jackson ObjectMapper 將 map 相同的 @JsonAlias 轉換為不同的 object 字段

[英]How to map same @JsonAlias to different object fields using Jackson ObjectMapper

在我的 DTO class 中,可能有一些字段可能具有相同的 @JsonAlias 值,但這似乎不適用於 Jackson ObjectMapper。

似乎 ObjectMapper 僅適用於第一次出現的 @JsonAlias 而不適用於具有相同值的 rest @JsonAlias。 我試圖在下面創建一個示例以供參考,在該示例中,Person class 有兩個名為 @JsonAlias 值的字段。

代碼片段

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;

public class Test {

  public static void main(String[] args) {

    Map<String, String> values = new HashMap<>();
    values.put("name", "TEST NAME");

    Person person = new ObjectMapper().convertValue(values, Person.class);
    System.out.println("name1: " + person.getName1());
    System.out.println("name2: " + person.getName2());
  }

  static class Person {
    @JsonAlias("name")
    String name1;

    @JsonAlias("name")
    String name2;

    public String getName1() {
      return name1;
    }

    public void setName1(String name1) {
      this.name1 = name1;
    }

    public String getName2() {
      return name2;
    }

    public void setName2(String name2) {
      this.name2 = name2;
    }
  }
}

Output :

name1: TEST NAME
name2: null

在上面的 output 中。我期待 Person class 中 name2 變量的“測試名稱”。

Jackson ObjectMapper 中是否有任何配置可以幫助我實現這一目標?

Jackson 版本-jackson-databind-2.11.4.jar

方案一, @JsonGetter @JsonSetter指向自定義的getter\setter
我們可以使用@JsonGetter("name" ) 和@JsonSetter("name")注釋來 map 一個 JSON 屬性值到具有處理兩個屬性的setter

public class Person {
    @JsonIgnore
    private String name1;

    @JsonIgnore
    private String name2;

    @JsonSetter("name")
    public void setName(String name) {
        this.name1 = name;
        this.name2 = name;
    }

    @JsonGetter("name")
    public String getName1() {
        return name1;
    }

    public void setName1(String name1) {
        this.name1 = name1;
    }

    public String getName2() {
        return name2;
    }

    public void setName2(String name2) {
      this.name2 = name2;
    }
}

解決方案2, @JsonAlias帶有特定的setter
我們可以忽略一個字段,第二個用別名標記,並添加一個自定義setName設置器,將一個 JSON 值映射到多個字段。

public class Person {
    @JsonAlias("name")
    private String name1;

    @JsonIgnore
    private String name2;

    public String getName1() {
        return name1;
    }

    public void setName1(String name1) {
        this.name1 = name1;
    }

    public String getName2() {
        return name2;
    }

    public void setName2(String name1) {
        this.name1 = name1;
    }

    public void setName(String name) {
        this.name1 = name;
        this.name2 = name;
    }
}

或者只是將自定義setName setter 添加到您的原始代碼中

public class Person {
    @JsonAlias("name")
    String name1;

    @JsonAlias("name")
    String name2;

    public String getName1() {
        return name1;
    }

    public void setName1(String name1) {
        this.name1 = name1;
    }

    public String getName2() {
        return name2;
    }

    public void setName2(String name1) {
        this.name1 = name1;
    }

    public void setName(String name) {
        this.name1 = name;
        this.name2 = name;
    }
}

解決方案3, @JsonProperty帶有特定的setter
與解決方案 2 相同,但改為使用@JsonProperty("name")

public class Person {
    @JsonProperty("name")
    private String name1;

    @JsonIgnore
    private String name2;

    public String getName1() {
        return name1;
    }

    @JsonIgnore
    public void setName1(String name1) {
        this.name1 = name1;
    }

    public String getName2() {
        return name2;
    }

    public void setName2(String name1) {
        this.name1 = name1;
    }

    public void setName(String name) {
        this.name1 = name;
        this.name2 = name;
    }
}

更新:
如果您沒有能力修改 DTO object,自定義反序列化器可以解決該問題。

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;

public class PersonDeserializer extends StdDeserializer<Person> {

    public PersonDeserializer() {
        this(null);
    }

    public PersonDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Person deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        Person person = new Person();

        JsonNode node = jp.getCodec().readTree(jp);
        String name =  node.get("name").asText();
        person.setName1(name);
        person.setName2(name);

        return person;
    }
}

將解串器應用於 DTO object:

@JsonDeserialize(using = PersonDeserializer.class)
public class Person {
    private String name1;
    private String name2;

    //getters and setters
}

或者在ObjectMapper上注冊自定義解串器

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Person.class, new PersonDeserializer());
        mapper.registerModule(module);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM