如何使用 Jackson 批注将嵌套值映射到属性?

2022-08-31 09:27:34

假设我正在调用一个 API,该 API 使用以下产品的 JSON 进行响应:

{
  "id": 123,
  "name": "The Best Product",
  "brand": {
     "id": 234,
     "name": "ACME Products"
  }
}

我能够使用Jackson注释很好地映射产品ID和名称:

public class ProductTest {
    private int productId;
    private String productName, brandName;

    @JsonProperty("id")
    public int getProductId() {
        return productId;
    }

    public void setProductId(int productId) {
        this.productId = productId;
    }

    @JsonProperty("name")
    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }
}

然后使用 fromJson 方法创建产品:

  JsonNode apiResponse = api.getResponse();
  Product product = Json.fromJson(apiResponse, Product.class);

但现在我试图弄清楚如何获取品牌名称,这是一个嵌套属性。我希望这样的东西会起作用:

    @JsonProperty("brand.name")
    public String getBrandName() {
        return brandName;
    }

但事实并非如此。有没有一种简单的方法可以使用注释来完成我想要的东西?

我试图解析的实际JSON响应非常复杂,我不想为每个子节点创建一个全新的类,即使我只需要一个字段。


答案 1

您可以像这样实现:

String brandName;

@JsonProperty("brand")
private void unpackNameFromNestedObject(Map<String, String> brand) {
    brandName = brand.get("name");
}

答案 2

这就是我处理这个问题的方式:

Brand类:

package org.answer.entity;

public class Brand {

    private Long id;

    private String name;

    public Brand() {

    }

    //accessors and mutators
}

Product类:

package org.answer.entity;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;

public class Product {

    private Long id;

    private String name;

    @JsonIgnore
    private Brand brand;

    private String brandName;

    public Product(){}

    @JsonGetter("brandName")
    protected String getBrandName() {
        if (brand != null)
            brandName = brand.getName();
        return brandName;
    }

    @JsonSetter("brandName")
    protected void setBrandName(String brandName) {
        if (brandName != null) {
            brand = new Brand();
            brand.setName(brandName);
        }
        this.brandName = brandName;
    }

//other accessors and mutators
}

此处,实例将被 期间 和 忽略,因为它用 注释。brandJacksonserializationdeserialization@JsonIgnore

Jackson将使用带有 for 注释的方法将 java 对象转换为格式。因此,设置为 .@JsonGetterserializationJSONbrandNamebrand.getName()

类似地,将使用带有 for format 注释的方法放入 java 对象中。在这种情况下,您必须自己实例化对象并从 中设置其属性。Jackson@JsonSetterdeserializationJSONbrandnamebrandName

如果希望持久性提供程序忽略持久性注释,则可以将持久性注释与 结合使用。@TransientbrandName