Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Jackson注释将嵌套值映射到属性?_Java_Json_Jackson - Fatal编程技术网

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

Java 如何使用Jackson注释将嵌套值映射到属性?,java,json,jackson,Java,Json,Jackson,假设我正在调用一个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 produ

假设我正在调用一个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响应非常复杂,我不想为每个子节点创建一个完整的新类,即使我只需要一个字段


您好,这是完整的工作代码。

//JUNIT测试类

公共类软件{

@Test
public void test() {

    Brand b = new Brand();
    b.id=1;
    b.name="RIZZE";

    Product p = new Product();
    p.brand=b;
    p.id=12;
    p.name="bigdata";


    //mapper
    ObjectMapper o = new ObjectMapper();
    o.registerSubtypes(Brand.class);
    o.registerSubtypes(Product.class);
    o.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

    String json=null;
    try {
        json = o.writeValueAsString(p);
        assertTrue(json!=null);
        logger.info(json);

        Product p2;
        try {
            p2 = o.readValue(json, Product.class);
            assertTrue(p2!=null);
            assertTrue(p2.id== p.id);
            assertTrue(p2.name.compareTo(p.name)==0);
            assertTrue(p2.brand.id==p.brand.id);
            logger.info("SUCCESS");
        } catch (IOException e) {

            e.printStackTrace();
            fail(e.toString());
        }




    } catch (JsonProcessingException e) {

        e.printStackTrace();
        fail(e.toString());
    }


}
}




**// Product.class**
    public class Product {
    protected int id;
    protected String name;

    @JsonProperty("brand") //not necessary ... but written
    protected Brand brand;

}

    **//Brand class**
    public class Brand {
    protected int id;
    protected String name;     
}
//junit测试用例的Console.log

2016-05-03 15:21:42 396 INFO  {"id":12,"name":"bigdata","brand":{"id":1,"name":"RIZZE"}} / MReloadDB:40 
2016-05-03 15:21:42 397 INFO  SUCCESS / MReloadDB:49 

完整的要点:

为了简单起见……我已经编写了代码……大部分内容是不言自明的

Main方法

package com.test;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class LOGIC {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        String DATA = "{\r\n" + 
                "  \"id\": 123,\r\n" + 
                "  \"name\": \"The Best Product\",\r\n" + 
                "  \"brand\": {\r\n" + 
                "     \"id\": 234,\r\n" + 
                "     \"name\": \"ACME Products\"\r\n" + 
                "  }\r\n" + 
                "}";

        ProductTest productTest = objectMapper.readValue(DATA, ProductTest.class);
        System.out.println(productTest.toString());

    }

}
Class ProductTest

package com.test;

import com.fasterxml.jackson.annotation.JsonProperty;

public class ProductTest {

    private int productId;
    private String productName;
    private BrandName 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;
    }

    @JsonProperty("brand")
    public BrandName getBrandName() {
        return brandName;
    }
    public void setBrandName(BrandName brandName) {
        this.brandName = brandName;
    }

    @Override
    public String toString() {
        return "ProductTest [productId=" + productId + ", productName=" + productName + ", brandName=" + brandName
                + "]";
    }



}
Class BrandName

package com.test;

public class BrandName {

    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "BrandName [id=" + id + ", name=" + name + "]";
    }




}
输出

ProductTest [productId=123, productName=The Best Product, brandName=BrandName [id=234, name=ACME Products]]

你可以这样做:

String brandName;

@JsonProperty("brand")
private void unpackNameFromNestedObject(Map<String, String> brand) {
    brandName = brand.get("name");
}
String品牌名称;
@JsonProperty(“品牌”)
NestedObject的私有名称(地图品牌){
brandName=brand.get(“name”);
}

您可以使用JsonPath表达式映射嵌套属性。我不认为有任何官方支持(请参阅问题),但这里有一个非官方的实现:

我就是这样处理这个问题的:

品牌
类别:

package org.answer.entity;

public class Brand {

    private Long id;

    private String name;

    public Brand() {

    }

    //accessors and mutators
}
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
}
产品
类别:

package org.answer.entity;

public class Brand {

    private Long id;

    private String name;

    public Brand() {

    }

    //accessors and mutators
}
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
}
这里,
brand
实例将被
Jackson
序列化
反序列化
期间忽略,因为它是用
@JsonIgnore
注释的

Jackson
将使用
@JsonGetter
注释的方法将java对象
序列化为
JSON
格式。因此,
brandName
设置为
brand.getName()

类似地,
Jackson
将使用
@JsonSetter
注释的方法将
JSON
格式的
反序列化为java对象。在这种情况下,您必须自己实例化
品牌
对象,并从
品牌名
设置其
名称
属性


如果希望持久性提供程序忽略它,可以将
@Transient
持久性注释与
品牌名一起使用。

最好使用setter方法:

JSON:

lat或lng的设置方法如下所示:

 @JsonProperty("coordinates")
    public void setLng(Map<String, String> coordinates) {
        this.lng = (Float.parseFloat(coordinates.get("lng")));
 }
@JsonProperty(“坐标”)
公共空间设置(地图坐标){
this.lng=(Float.parseFloat(coordinates.get(“lng”));
}
如果您需要同时读取这两个文件(通常会这样做),则使用自定义方法

@JsonProperty("coordinates")
public void setLatLng(Map<String, String> coordinates){
    this.lat = (Float.parseFloat(coordinates.get("lat")));
    this.lng = (Float.parseFloat(coordinates.get("lng")));
}
@JsonProperty(“坐标”)
公共空间设置(地图坐标){
this.lat=(Float.parseFloat(coordinates.get(“lat”));
this.lng=(Float.parseFloat(coordinates.get(“lng”));
}

这是可行的,但我正在尝试找到一种解决方案,即使我只需要一个字段,也不必为每个节点创建新类。我尝试映射的实际JSON响应非常复杂。它有很多节点和子节点,为每个节点创建一个类将非常痛苦,在大多数情况下,我只需要一个字段时更是如此一组三层嵌套的节点。难道没有办法只获取单个字段而不必创建大量新类吗?打开一个新的sof票证并与我共享,我可以在这方面帮助您。请共享您想要映射的json结构。:)三层深度如何?@Robin不管用吗?
this.缩写=((map)portalCharacteristics.get(“icon”).get(“ticker”).toString();
同样的方法也可以用于解包多个值…解包来自NestedBrand的值-感谢三个级别直接使用JsonNode。映射变得太麻烦:
void解包名称(JsonNode公司){name=company.get(“division”).get(“brand”).get(“name”).asText();}
我最后使用了-Spring,它也在引擎盖下使用。例如,在他们的org.springframework.data.web中。