Jackson条件性 @JsonUnwrapped

5

我可以有条件地使用@JsonUnwrapped吗?我不想在序列化期间使用它,但希望在反序列化对象时使用它。

一种方法是创建两个不同的类或创建一个子类,覆盖仅需要在序列化和反序列化时表现不同的属性。这听起来不太合适。还有其他替代方案或Jackson解决该问题的方法吗?

2个回答

5
你可以使用 MixIn 特性。使用此特性,POJO类与Jackson注释解耦。你可以在运行时使用MixIn添加必要的注释。请参见以下示例:
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonTest {

    private static final String UNWRAPPED_JSON = "{\n" +
            "  \"age\" : 13,\n" +
            "  \"first\" : \"Huckleberry\",\n" +
            "  \"last\" : \"Finn\"\n" +
            "}";

    @Test
    public void test() throws IOException {
        System.out.println("### Serialize without unwrapped annotation ###");
        ObjectMapper serializer = new ObjectMapper();
        System.out.println(serializer.writerWithDefaultPrettyPrinter().writeValueAsString(createParent()));

        System.out.println("### Deserialize with unwrapped annotation ###");
        ObjectMapper deserializer = new ObjectMapper();
        deserializer.addMixInAnnotations(Parent.class, ParentMixIn.class);
        System.out.println(deserializer.readValue(UNWRAPPED_JSON, Parent.class));
    }

    private Parent createParent() {
        Name name = new Name();
        name.first = "Tom";
        name.last = "Sawyer";

        Parent parent = new Parent();
        parent.setAge(12);
        parent.setName(name);

        return parent;
    }
}

class Parent {

    private int age;
    private Name name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Name getName() {
        return name;
    }

    public void setName(Name name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Parent{" +
                "age=" + age +
                ", name=" + name +
                '}';
    }
}

interface ParentMixIn {

    @JsonUnwrapped
    Name getName();
}

class Name {

    public String first, last;

    @Override
    public String toString() {
        return "Name{" +
                "first='" + first + '\'' +
                ", last='" + last + '\'' +
                '}';
    }
}

上面的程序打印出:
### Serialize without unwrapped annotation ###
{
  "age" : 12,
  "name" : {
    "first" : "Tom",
    "last" : "Sawyer"
  }
}

### Deserialize with unwrapped annotation ###
Parent{age=13, name=Name{first='Huckleberry', last='Finn'}}

这种混合特性可以用于深度嵌套的对象吗?例如,对象A解嵌套对象B,然后解嵌套对象B中的对象C。 - experiment unit 1998X
1
给所有未来的观众注意 - 是的,这是可能的。mapper.addMixIn(compA.class, compAMixIn.class); mapper.addMixIn(compB.class, compBMixIn.class); mapper.convertValue(...)' 假设compAMixIn解开了compB,而compBMixIn解开了compC。 - experiment unit 1998X

3
有一种更简单的方法,只基于注解即可实现相同的结果:
@JsonUnwrapped(prefix = "name_")
@JsonProperty(access = READ_ONLY)
private Name nameObject;

// method will deserialize original JSON and set it to unwrapped field
@JsonSetter
public void setName(Name name) {
  this.nameObject = name;
}

// simple getter
@JsonIgnore
public Name getName() {
  return this.nameObject;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接