2015-12-10 18 views
9

Jackson prende in considerazione molti fattori quando si nomina un campo per la serializzazione in JSON. È possibile utilizzare questi fattori al contrario per recuperare il valore di un campo in un pojo in base al nome che avrà una volta serializzato?È possibile utilizzare Jackson per ottenere il valore da Pojo

Ad esempio, dato il fagiolo

public class Bean{ 
    private Bean2 prop; 

    @JsonProperty("property") 
    public Bean2 getProp(); 
} 

E 'possibile ottenere il valore di prop dato solo un configurato ObjectMapper, la stringa "property" e un'istanza di Bean?

Conosco la riflessione, quindi se potessi semplicemente ottenere "prop" o "getProp" sarei praticamente pronto.

+1

Certo, basta elencare i campi/metodi getter della classe e cercare '@ JsonProperty'. Questo suona terribilmente invadente, tuttavia, e potrebbe esserci un'opzione migliore se spiegassi in modo specifico quale sia il tuo caso d'uso. – chrylis

+0

Hai bisogno di un buon motivo per farlo per farmi approvare. Uno dei punti di strumenti come Jackson è quello di disaccoppiare la tua logica, che presumibilmente vorrebbe usare gli oggetti POJO dal trasferimento/DTO. –

+0

@chrylis Ho appena usato '@ JsonProperty' per dimostrare come il nome del campo può essere un valore inaspettato, l'annotazione non sarà sempre lì. – kag0

risposta

2

è possibile serializzare il Bean in una stringa JSON, quindi deserializzare la stessa JSON String in una mappa (basta chiamare ObjectMapper.readValue(JsonString, Map.class)) e allora si può fare Map.get("property") e lo avete. Ecco una soluzione one-liner:

String property = ((Map<String, Object>)mapper.readValue(mapper.writeValueAsString(bean), Map.class)).get("property").toString(); 
+0

In realtà è possibile convertire direttamente in una mappa usando 'mapper.convertValue (bean, Map.class)'. Ma Jackson deserializzerà i campi oggetto come mappe. Quindi se 'prop' era di tipo' Bean2', 'mapper.convertValue (bean, Map.class) .get (" prop ")' restituirebbe 'Map '. Sto cercando di ottenere 'prop' come un pojo. – kag0

4

È possibile de-serializzare dato JSON String in Bean. Quindi è possibile trovare la proprietà utilizzando il metodo get() di JsonNode e successivamente è possibile ottenere il valore come POJO utilizzando il metodo treeToValue().

E.g.

 ObjectMapper mapper = new ObjectMapper(); 

     JsonNode rootNode = mapper.readValue(new ObjectMapper().writeValueAsString(bean), JsonNode.class); 

     JsonNode propertyNode = rootNode.get("property"); 

     Class<?> propertyField = null; 

     Field []fields = Bean.class.getDeclaredFields(); 

     for (Field field : fields){ 

      //First checks for field name 
      if(field.equals("property")){ 

       propertyField = field.getType(); 
        break; 
      } 
      else{ 

       //checks for annotation name 
       if (field.isAnnotationPresent(JsonProperty.class) && field.getAnnotation(JsonProperty.class).value().equals("property")) { 
        propertyField = field.getType(); 
        break; 
       } 
       //checks for getters 
       else { 

        PropertyDescriptor pd = new PropertyDescriptor(field.getName(), Bean.class); 

        Method getMethod = pd.getReadMethod(); 

        if (getMethod.isAnnotationPresent(JsonProperty.class) && getMethod.getAnnotation(JsonProperty.class).value().equals("property")) { 

         propertyField = field.getType(); 

         break; 
        } 
       } 
      } 
      } 


     if(propertyField != null){ 

      Object o = mapper.treeToValue(propertyNode, propertyField); 

     } 
+0

Questo potrebbe funzionare, ma come posso sapere il tipo di 'propertyNode'?Come indicato nella domanda, ho solo un ObjectMapper configurato, la stringa "proprietà" e un'istanza di 'Bean'. Quindi non ho conoscenza della classe 'Bean' prima del runtime. – kag0

+0

@ kag0 bene in tal caso, è necessario utilizzare la riflessione per capire il tipo di campo di quel particolare nome. Controlla il mio codice aggiornato, in cui ho cercato di trovare il tipo che appartiene al nome di una particolare proprietà. –

+0

Sono consapevole del fatto che posso usare il reflection in questo modo (anche se non conoscevo 'PropertyDescriptor', quindi è utile). Voglio sapere se c'è un modo specifico per usare Jackson, invece di fare tutto il riflesso da solo. Inoltre, il tuo codice non funzionerebbe se il campo JSON provenisse da un getter senza campo java corrispondente, o se il campo fosse ereditato. – kag0