Jackson Parse Tree Answer

I want to parse the answer to neighboring Google places, the element has this format:

"geometry" : { "location" : { "lat" : 75.22404, "lng" : 57.42276 }, "viewport" : { "northeast" : { "lat" : 95.2353532, "lng" : 75.4427513 }, "southwest" : { "lat" : 55.207256, "lng" : 45.4045009 } } }, "vicinity" : "something" 

But I want to parse this using only one object, something like this:

 public class NearbyPlace extends BaseResponse { @JsonProperty("how to access geometry->lat ?") private double latitude; @JsonProperty("how to access geometry->lng ?") private double longitude; @JsonProperty("vicinity") private String vicinity; } 

The problem is how to access the "lat" and "lng" in the "geometry" directly from the NearPlace class without creating other classes for each node?

+5
source share
3 answers

You can use a combination of readTree() and treeToValue() :

 final String placesResponse = "..."; final ObjectMapper om; NearbyPlace place = null; final JsonNode placesNode = om.readTree(placesResponse); final JsonNode locationNode = placesNode.findPath("geometry").findPath("location"); if (! locationNode.isMissingNode()) { place = om.treeToValue(locationNode, NearbyPlace.class); } 

However, since the vicinity is stored outside the internal geometry class, you still need to set this value manually. JsonNode has the required methods:

 final JsonNode vicinityNode = placesNode.findPath("vicinity"); if (vicinityNode.isTextual()) { place.vicinity = vicinityNode.textValue(); } 
0
source

Since you get the NearbyPlace s collection, it might be best for you to just navigate the JsonNode screen. Otherwise, you're talking about redefining deserialization for collections or writing a deserializer that can become annoying.

The example below is recursive. Recursion in Java is bad (at the moment), but interesting to write. In a working application, I recommend a loop.

 @Test public void testNearbyPlaceDeserialization() throws Exception { JsonNode jsonNode = objectMapper.readTree(new File("input.json")); // or objectMapper.readValue(resultString, JsonNode.class); ImmutableList<NearbyPlace> nearbyPlaces = readLatLng(jsonNode, jsonNode.get("vicinity").asText(null), ImmutableList.builder()); System.out.println(nearbyPlaces); } private static ImmutableList<NearbyPlace> readLatLng(JsonNode jsonNode, String vicinity, ImmutableList.Builder<NearbyPlace> placeBuilder) { JsonNode latNode = jsonNode.get("lat"); JsonNode lngNode = jsonNode.get("lng"); if (latNode != null && lngNode != null) { placeBuilder.add(NearbyPlace.builder() .setLatitude(latNode.asDouble()) .setLongitude(lngNode.asDouble()) .setVicinity(vicinity) .build()); } else { jsonNode.elements().forEachRemaining((element) -> { readLatLng(element, vicinity, placeBuilder); }); } return placeBuilder.build(); } 

This will return a list of 3 NearbyPlace s.

0
source

The easiest solution I can think of is to use the @JsonCreator annotation in the NearbyPlace class constructor

:
 public class NearbyPlace extends BaseResponse { private double latitude; private double longitude; @JsonProperty("vicinity") private String vicinity; @JsonCreator public NearbyPlace(Map<String, Object> delegate) { super(); this.latitude = (Double) delegate.get("geometry").get("location").get("lat"); this.latitude = (Double) delegate.get("geometry").get("location").get("lng"); } } 

You might want to add some checks against null if the incoming JSON is missing some nested object, i.e. geometry or location .

See the Jackson annotation documentation for more details.

0
source

All Articles