杰克逊建造者模式从父母那里获得价值

时间:2018-08-17 16:08:40

标签: java json jackson

我正在尝试使用杰克逊从父节点获取值。

我知道使用自定义反序列器可以实现此目的,但是样板太多了,因为您突然不得不手动处理所有事情。

这听起来很简单,但没有找到解决方法。

举例说明我想要的-如果我们有一个简单的UserAddress ...

@JsonDeserialize(builder = User.Builder.class)
public class User
{
  private long id;
  private String firstName;
  private Address address;
  ...

  public static class Builder
  {
    public Builder withId(long id);
    public Builder withFirstName(String value);
    public Builder withAddress(Address address);
    public User create();
  }
}

如果我们的地址相同

@JsonDeserialize(builder = Address.Builder.class)
public class Address
{
  ...

  public static class Builder
  {
    public Builder withUserId(long id); // is there a way to ask for the parent id here?
    public Builder withStreetName(String value);
    public Address create();
  }
}

样本输入:

{
    "id": 7,
    "firstName" : "John",
    "lastName" : "Smith",
    "address" : {
        "streetName": "1 str"
    }
}

1 个答案:

答案 0 :(得分:0)

不,我认为您无法使用任何现有的Jackson代码。我认为唯一可以跨越这样的父子关系的是类型序列化/反序列化和UNWRAP_ROOT_VALUE支持。

如果您想要这样的话,则需要为User使用自定义反序列化器,或者自定义User构造函数以使用正确的UserId构建新地址,然后再将其添加到建造者的内部状态。这是一个示例(使用Lombok来处理生成器的样板生成):

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

import lombok.Builder;
import lombok.Value;
import lombok.experimental.Wither;

public class Scratch {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"id\":1234,\"address\":{\"street\":\"123 Main St.\"}}";

        User user = mapper.readValue(json, User.class);

        System.out.println(user.toString());

    }


    @Value
    @JsonDeserialize(builder = User.UserBuilder.class)
    public static class User {
        private final int id;
        private final Address address;


        @Builder(toBuilder = true)
        public User(int id, Address address) {
            this.id = id;
            // Build a new address with the user's ID
            this.address = address.withUserId(id);
        }

        @JsonPOJOBuilder(withPrefix = "")
        public static class UserBuilder {}
    }


    @Value
    @Builder(toBuilder = true)
    @JsonDeserialize(builder = Address.AddressBuilder.class)
    public static class Address {

        @Wither
        private final int userId;

        private final String street;

        @JsonPOJOBuilder(withPrefix = "")
        public static class AddressBuilder {}
    }

}

这会消耗以下json:

{
    "id":      1234,
    "address": {
        "street": "123 Main St."
    }
}

并产生以下输出:

Scratch.User(id=1234, address=Scratch.Address(userId=1234, street=123 Main St.))