如何使用Jackson ObjectMapper将相同的@jsonalias映射到不同的对象字段

发布于 2025-01-25 18:41:00 字数 1356 浏览 1 评论 0 原文

在我的DTO类中,可能会有可能具有相同的@jsonalias值的字段,但这似乎与Jackson ObjectMapper不起作用。

看来ObjectMapper仅适用于@jsonalias的首次出现,并且对其余的@jsonalias不起作用,@jsonalias具有相同的值。我试图在下面创建一个示例以供参考,在该示例中,Person类具有具有名称@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;
    }
  }
}

输出

name1: TEST NAME
name2: null

在上述输出中。我期望在同类中为NAME2变量提供“测试名称”。

Jackson ObjectMapper中是否有任何配置可以帮助我实现这一目标?

杰克逊版-Jackson-Databind-2.11.4.jar

In my DTO class, there could be fields which might have same @JsonAlias values, but this seems not working with Jackson ObjectMapper.

It seems that ObjectMapper only works for the first occurrence of @JsonAlias and it don't work for the rest @JsonAlias which has same value. I have tried to create an example below for the reference and in that example, Person class has the two fields with name @JsonAlias value.

Code snippet:

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

In the above output. I was expecting the "TEST NAME" for the name2 variable in Person class.

Is there any configuration in Jackson ObjectMapper which will help me to achieve this?

Jackson version - jackson-databind-2.11.4.jar

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

往日情怀 2025-02-01 18:41:00

解决方案1, @jsongetter @jsonsetter 指出指向自定义getter \ setter

我们可以使用)和 @jsonsetter(“ name”)注释将一个JSON属性值映射到具有处理两个属性

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 setter将一个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;
    }
}

或者只需在您的原始代码

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对象的能力,则自定义求职者可以解决该问题。

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;
    }
}

将Deserializer应用于DTO对象:

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

    //getters and setters
}

或在 ObjectMapper 上注册Custom Deserializer

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

Solution 1, @JsonGetter @JsonSetter point out to the custom getter\setter

We can use @JsonGetter("name") and @JsonSetter("name") annotations to map one JSON property value to the setter which has handling two properties

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;
    }
}

Solution 2, @JsonAlias with the specific setter

We can ignore one field, the second mark with an alias, and add a custom setName setter that maps one JSON value to several fields.

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;
    }
}

Or just add a custom setName setter to your original code

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;
    }
}

Solution 3, @JsonProperty with the specific setter

The same like Solution 2, but instead use @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;
    }
}

UPDATE:

In case you do not have the ability to modify DTO object, custom deserializer resolve the problem.

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;
    }
}

Apply deserializer to the DTO object:

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

    //getters and setters
}

OR register custom deserializer on ObjectMapper

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Person.class, new PersonDeserializer());
        mapper.registerModule(module);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文