【问题标题】:Jackson builder pattern get value from parent杰克逊建造者模式从父母那里获得价值
【发布时间】:2018-08-17 16:08:40
【问题描述】:

我正在尝试使用 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"
    }
}

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    不,我认为您不能使用任何现有的杰克逊代码。我认为唯一可以像这样跨父/子关系的是类型序列化/反序列化和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.))
    

    【讨论】:

      猜你喜欢
      • 2011-06-26
      • 1970-01-01
      • 2019-06-16
      • 1970-01-01
      • 2018-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多