Jackson JSON Java вложенные объекты и массивы
У меня есть пример вложенного объекта json, как показано ниже:
{
"payload": {
"id": "1",
"apiResp": {
"apiRespDetails": {
"report": {
"reportId": "reportid1",
"reportDetails": [
{
"code": "1",
"rating": "good"
},
{
"code": "2",
"rating": "bad"
},
{
"code": "3",
"rating": "fair"
}
]
}
}
}
}
}
Мне нужен только объект report, мне не нужны никакие детали его родительского объекта. Каков был бы лучший способ получить именно это, используя API Джексона ?
Я создал класс Java под названием Report.java с полями reportId (строка) и reportDetails (список ReportDetail), где ReportDetail-это другой класс со строковым кодом полей, рейтингом и т. д. Нужно ли мне использовать какой-то десериализатор, JsonTreeParser механизм?Спасибо.
2 ответов:
Решением для этого являетсяреализация Java jayway для JsonPath .
JsonPath является эквивалентом json для языка запросов XPath для XML. язык запросов довольно мощный, как видно из примеров на GitHub readme.Вот краткое демо, чтобы вы начали:
import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.*; import com.jayway.jsonpath.*; import net.minidev.json.JSONArray; import static com.jayway.jsonpath.matchers.JsonPathMatchers.*; public class JsonPathDemo2 { public static void main(String[] args) { // query: search for any report property below root String jsonPathQuery = "$..report"; try (InputStream is = Files.newInputStream(Paths.get("C://temp/xx.json"))) { Object parsedContent = Configuration.defaultConfiguration().jsonProvider().parse(is, StandardCharsets.UTF_8.name()); System.out.println("hasJsonPath? " + hasJsonPath(jsonPathQuery).matches(parsedContent)); Object obj = JsonPath.read(parsedContent, jsonPathQuery); System.out.println("parsed object is of type " + obj.getClass()); System.out.println("parsed object to-string " + obj); JSONArray arr = (JSONArray)obj; System.out.println("first array item is of type " + arr.get(0).getClass()); System.out.println("first array item to-string " + arr.get(0)); } catch (Exception e) { e.printStackTrace(); } } }Вывод:
hasJsonPath? true parsed object is of type class net.minidev.json.JSONArray parsed object to-string [{"reportId":"reportid1","reportDetails":[{"code":"1","rating":"good"},{"code":"2","rating":"bad"},{"code":"3","rating":"fair"}]}] first array item is of type class java.util.LinkedHashMap first array item to-string {reportId=reportid1, reportDetails=[{"code":"1","rating":"good"},{"code":"2","rating":"bad"},{"code":"3","rating":"fair"}]}
Hi нашел два решения, используя jackson fasterxml api.
В первом вы можете просто использовать метод findValue на jsonNode и передать строковое значение свойства / объекта, который вы ищете
String jsonresponse = "above json string"; JsonFactory jsonFactory = new JsonFactory(); JsonParser jp = jsonFactory.createParser(jsonresponse); jp.setCodec(new ObjectMapper()); JsonNode jsonNode = jp.readValueAsTree(); JsonNode reportNode = jsonNode.findValue("report"); ObjectMapper mapper = new ObjectMapper(); Report report = mapper.convertValue(reportNode, Report.class);Это другое решение использует JsonToken, который перемещает ответ json, пока вы не найдете то, что ищете
JsonFactory factory = new JsonFactory(); factory.setCodec(new ObjectMapper()); JsonParser parser = factory.createParser(jsonresponse); while(!parser.isClosed()){ JsonToken jsonToken = parser.nextToken(); if(JsonToken.FIELD_NAME.equals(jsonToken)){ String fieldName = parser.getCurrentName(); if("report".equals(fieldName)) { jsonToken = parser.nextToken(); Report report = parser.readValueAs(Report.class); } else { jsonToken = parser.nextToken(); } } }
Comments