ken*_*ske 75 java json jackson
假设我正在调用一个API,它响应产品的以下JSON:
{
"id": 123,
"name": "The Best Product",
"brand": {
"id": 234,
"name": "ACME Products"
}
}
Run Code Online (Sandbox Code Playgroud)
我可以使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用fromJson方法创建产品:
JsonNode apiResponse = api.getResponse();
Product product = Json.fromJson(apiResponse, Product.class);
Run Code Online (Sandbox Code Playgroud)
但现在我想弄清楚如何获取品牌名称,这是一个嵌套的属性.我希望这样的东西能起作用:
@JsonProperty("brand.name")
public String getBrandName() {
return brandName;
}
Run Code Online (Sandbox Code Playgroud)
但当然没有.有没有一种简单的方法可以使用注释来实现我想要的东西?
我试图解析的实际JSON响应非常复杂,我不想为每个子节点创建一个完整的新类,即使我只需要一个字段.
小智 77
你可以这样做:
String brandName;
@JsonProperty("brand")
private void unpackNameFromNestedObject(Map<String, String> brand) {
brandName = brand.get("name");
}
Run Code Online (Sandbox Code Playgroud)
小智 7
这就是我处理此问题的方式:
Brand 类:
package org.answer.entity;
public class Brand {
private Long id;
private String name;
public Brand() {
}
//accessors and mutators
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
在此,brand实例将Jackson在serialization和中被忽略deserialization,因为该实例用注释@JsonIgnore。
Jackson将使用java对象的@JsonGetterfor 注释方法serialization转换为JSON格式。因此,用brandName设置brand.getName()。
同样地,Jackson将使用与注释的方法@JsonSetter为deserialization的JSON格式转换成Java对象。在这种情况下,您将必须自己实例化该brand对象并name从中设置其属性brandName。
您可以使用@Transient持久性与注释brandName,如果你想让它通过持久性提供被忽略。
您可以使用 JsonPath 表达式来映射嵌套属性。我认为没有任何官方支持(请参阅此问题),但这里有一个非官方实现:https : //github.com/elasticpath/json-unmarshaller
最好是使用 setter 方法:
JSON:
...
"coordinates": {
"lat": 34.018721,
"lng": -118.489090
}
...
Run Code Online (Sandbox Code Playgroud)
lat 或 lng 的 setter 方法如下所示:
@JsonProperty("coordinates")
public void setLng(Map<String, String> coordinates) {
this.lng = (Float.parseFloat(coordinates.get("lng")));
}
Run Code Online (Sandbox Code Playgroud)
如果您需要阅读两者(就像通常所做的那样),那么使用自定义方法
@JsonProperty("coordinates")
public void setLatLng(Map<String, String> coordinates){
this.lat = (Float.parseFloat(coordinates.get("lat")));
this.lng = (Float.parseFloat(coordinates.get("lng")));
}
Run Code Online (Sandbox Code Playgroud)