Допустим, я вызываю API, который отвечает следующим JSON для продукта:
{
"id": 123,
"name": "The Best Product",
"brand": {
"id": 234,
"name": "ACME Products"
}
}
Я могу легко сопоставить идентификатор продукта и имя, используя аннотации Джексона:
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, который я пытаюсь проанализировать, очень сложен, и я не хочу создавать целый новый класс для каждого подузла, хотя мне нужно только одно поле.
Ответы:
Добиться этого можно так:
String brandName; @JsonProperty("brand") private void unpackNameFromNestedObject(Map<String, String> brand) { brandName = brand.get("name"); }
источник
this.abbreviation = ((Map<String, Object>)portalCharacteristics.get("icon")).get("ticker").toString();
Вот как я справился с этой проблемой:
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 }
Здесь
brand
экземпляр будет проигнорированJackson
во времяserialization
иdeserialization
, поскольку он помечен@JsonIgnore
.Jackson
будет использовать метод, аннотированный@JsonGetter
дляserialization
объекта java, вJSON
формат. Итак,brandName
устанавливается сbrand.getName()
.Точно так же
Jackson
будет использоваться метод, помеченный@JsonSetter
дляdeserialization
ofJSON
format в java-объект. В этом сценарии вам нужно будет самостоятельно создать экземплярbrand
объекта и установить егоname
свойство изbrandName
.Вы можете использовать
@Transient
аннотацию сохраняемости сbrandName
, если хотите, чтобы поставщик сохраняемости игнорировал ее.источник
Вы можете использовать JsonPath-выражения для сопоставления вложенных свойств. Я не думаю, что есть официальная поддержка (см. Этот вопрос), но здесь есть неофициальная реализация: https://github.com/elasticpath/json-unmarshaller
источник
Лучше всего использовать методы установки:
JSON:
... "coordinates": { "lat": 34.018721, "lng": -118.489090 } ...
Метод установки для lat или lng будет выглядеть так:
@JsonProperty("coordinates") public void setLng(Map<String, String> coordinates) { 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"))); }
источник
Чтобы упростить ... Я написал код ... большая часть его не требует пояснений.
Main Method
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 + "]"; } }
OUTPUT
ProductTest [productId=123, productName=The Best Product, brandName=BrandName [id=234, name=ACME Products]]
источник
Привет, вот полный рабочий код.
// JUNIT TEST CLASS
public class sof {
@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; }
//Console.log тестового примера junit
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
Полная суть: https://gist.github.com/jeorfevre/7c94d4b36a809d4acf2f188f204a8058
источник