2011-08-12 13 views
8

Sono consapevole del fatto che ci sono molti modi per dire a JacksonJson di ignorare le proprietà durante il rendering, ma tutte sono statiche. (JasonIgnore, lezioni MixIn, ..).Ignora dinamicamente le proprietà con JacksonJson

Questo è il mio scenario. Un oggetto dominio può implementare un'interfaccia chiamata FilteredDomain su consentire che venga filtrato in modo dinamico. L'interfaccia è semplice e espone solo un metodo "getIgnoreProperties". (Un elenco di proprietà da ignorare).

Poi registro un serializzatore personalizzato che si collega all'oggetto FilteredDomain. Il codice simile a:

private class FilteredDomainSerializer extends JsonSerializer<FilteredDomain> { 

    public void serialize(FilteredDomain arg, JsonGenerator jgen, 
      SerializerProvider provder) throws IOException, 
      JsonProcessingException { 

     final BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(arg); 

     for (PropertyDescriptor pd : wrapper.getPropertyDescriptors()) { 
      final String name = pd.getName(); 

      if (arg.getIgnoreProperties().containsKey(name)) 
       continue; 

      final Object value = wrapper.getPropertyValue(name); 

      jgen.writeObjectField(name, value); 
     } 
    } 
} 

In primo luogo, mi piace davvero che ho bisogno di utilizzare il wrapper primavera Bean per ottenere un elenco di tutte le proprietà e scorrere attraverso di loro (ci deve essere un modo per fare questo è Jackson jSON).

In secondo luogo, il codice continua a non funzionare. Ottengo l'errore:

org.codehaus.jackson.JsonGenerationException: Impossibile scrivere un nome di campo, in attesa di un valore di a org.codehaus.jackson.impl.JsonGeneratorBase._reportError (JsonGeneratorBase.java:480) a org .codehaus.jackson.impl.Utf8Generator.writeFieldName (Utf8Generator.java:270) a org.codehaus.jackson.JsonGenerator.writeObjectField (JsonGenerator.java:1088) a com.rootmusic.util.SystemJsonObjectMapper $ ValueObjectSerializer.serialize (SystemJsonObjectMapper .java: 65) su com.rootmusic.util.SystemJsonObjectMapper $ ValueObjectSerializer.serialize (SystemJsonObjectMapper.java:1) all'indirizzo org.codehaus.jackson.map.ser.ContainerSerializers $ IndexedListSerializer.serializeContents (ContainerSe rializers.java:304) all'indirizzo org.codehaus.jackson.map.ser.ContainerSerializers $ IndexedListSerializer.serializeContents (ContainerSerializers.java:254) all'indirizzo org.codehaus.jackson.map.ser.ContainerSerializers $ AsArraySerializer.serialize (ContainerSerializers. java: 142) in org.codehaus.jackson.map.ser.MapSerializer.serializeFields (MapSerializer.java:287) all'indirizzo org.codehaus.jackson.map.ser.MapSerializer.serialize (MapSerializer.java:212) presso org.codehaus.jackson.map.ser.MapSerializer.serialize (MapSerializer.java:23) all'indirizzo org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue (StdSerializerProvider.java:606) presso org.codehaus.jackson. map.ser.StdSerializerProvider.serializeValue (StdSerializerProvider.java:280)

risposta

8

L'errore deriva dal fatto che non si sta scrivendo START_OBJECT/END_OBJECT attorno alle coppie nome-campo/valore, quindi è facile correggerle.

Per quanto riguarda il filtraggio più dinamico, è possibile leggere this blog entry che include i metodi standard. @JsonView funziona se si hanno set di definizioni statiche (una delle quali è possibile selezionare dinamicamente in base alla serializzazione), ma se si desidera un sistema ancora più dinamico, @JsonFilter è la strada da percorrere.

In alternativa, un altro modo relativamente semplice sarebbe quella di prima "convertire" il tuo POJO in una mappa:

Mappa props = objectMapper.convertValue (POJO, Map.class);

(che è simile a serializzazione come JSON, tranne che risultato è una mappa che renderebbe come JSON)

e quindi selettivamente assetto Map e serializzare che come JSON.Oppure, se preferisci, puoi usare JsonNode ("modello ad albero") come elemento intermedio da modificare e quindi serializzare.

Problemi correlati