2015-07-09 7 views
5

voglio analizzare google vicina risposta luoghi, un articolo ha questo formato:Jackson analizzare la risposta albero

  "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" 

Ma voglio analizzare questo utilizzando solo un oggetto qualcosa di simile:

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; 
} 

Il problema è come accedere a "lat" e "lng" in "geometry" direttamente dalla classe NearbyPlace senza creare altre classi per ogni nodo?

+0

Non dovrebbe esserci una collezione da qualche parte? O una collezione di 'NearbyPlace's o collezioni di' lattittude's e 'longitude's all'interno di' NearbyPlace'? –

+0

NearbyPlace è un elemento della raccolta. – GeniDeveloper

risposta

0

è possibile utilizzare una combinazione di readTree() e 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); 
} 

Tuttavia, dal momento che vicinity tenuti al di fuori della classe geometria interna, è ancora necessario impostare manualmente il valore. JsonNode ha i metodi necessari:

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

Grazie per la risposta, ma sto usando un ObjectMapper per mappare tutto il tipo di classe: result = (T) objectMapper.readValue (resultString, aClass); Quindi ho bisogno di risolvere il mio problema all'interno della classe mappata, in questo caso: NearbyPlace – GeniDeveloper

0

Dal momento che si finirà con una collezione di NearbyPlace s, si può essere meglio fuori appena attraversano manualmente il JsonNode. Altrimenti si parla di deserializzazione prioritaria per le raccolte o di scrittura di un deserializzatore che rischia di diventare sgradevole.

L'esempio di seguito è ricorsivo. La ricorsione in Java è bad (per ora), ma divertente da scrivere. In un'app di produzione raccomanderei un ciclo.

@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(); 
} 

Ciò restituirà un elenco di 3 NearbyPlace s.

0

La soluzione più semplice mi viene in mente è quello di utilizzare il @JsonCreator annotazioni sulla NearbyPlace classe costruttore:

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"); 
    } 
} 

Si potrebbe desiderare di aggiungere alcuni controlli contro null nel caso in cui il JSON in entrata manca qualche oggetto nidificato, cioè geometry o location.

Per ulteriori dettagli, fare riferimento a Jackson annotations documentation.

+1

Grazie per la risposta, sembra utile ma non posso testarlo oggi. Proverò a testarlo domani e dare un feedback. – GeniDeveloper

+0

Ho controllato e ora ho il valore di latitudine e longitudine ma tutti gli altri campi che usano le annotazioni sono nulli, avete un'idea? – GeniDeveloper

+0

Bene. .. havent testato. Forse devi estrarli dalla mappa delegata nel costruttore e assegnare ogni valore all'attributo corrispondente. –