2011-08-12 24 views
8

Soy consciente de que hay muchas maneras de decirle a JacksonJson que ignore las propiedades durante el procesamiento, pero todas ellas son estáticas. (JasonIgnore, clases MixIn, ..).Ignorar dinámicamente las propiedades con JacksonJson

Este es mi escenario. Un objeto de dominio puede implementar una interfaz llamada FilteredDomain en que permite que se filtre dinámicamente. La interfaz es simple y solo expone un método "getIgnoreProperties". (Una lista de propiedades para ignorar).

Luego registro un serializador personalizado que se une al objeto FilteredDomain. El código se ve algo como:

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

En primer lugar, no me gusta la que tengo que utilizar el contenedor de beans Spring para obtener una lista de todas las propiedades e iterar a través de ellos (que debe haber una manera de hacer esto es Jackson json).

En segundo lugar, el código aún no funciona. Me sale el error:

org.codehaus.jackson.JsonGenerationException: No se puede escribir un nombre de campo, esperando un valor en org.codehaus.jackson.impl.JsonGeneratorBase._reportError (JsonGeneratorBase.java:480) en org .codehaus.jackson.impl.Utf8Generator.writeFieldName (Utf8Generator.java:270) en org.codehaus.jackson.JsonGenerator.writeObjectField (JsonGenerator.java:1088) en com.rootmusic.util.SystemJsonObjectMapper $ ValueObjectSerializer.serialize (SystemJsonObjectMapper .java: 65) en com.rootmusic.util.SystemJsonObjectMapper $ ValueObjectSerializer.serialize (SystemJsonObjectMapper.java:1) en org.codehaus.jackson.map.ser.ContainerSerializers $ IndexedListSerializer.serializeContents (ContainerSe rializers.java:304) en org.codehaus.jackson.map.ser.ContainerSerializers $ IndexedListSerializer.serializeContents (ContainerSerializers.java:254) en org.codehaus.jackson.map.ser.ContainerSerializers $ AsArraySerializer.serialize (ContainerSerializers. java: 142) en org.codehaus.jackson.map.ser.MapSerializer.serializeFields (MapSerializer.java:287) en org.codehaus.jackson.map.ser.MapSerializer.serialize (MapSerializer.java:212) en org.codehaus.jackson.map.ser.MapSerializer.serialize (MapSerializer.java:23) en org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue (StdSerializerProvider.java:606) en org.codehaus.jackson. map.ser.StdSerializerProvider.serializeValue (StdSerializerProvider.java:280)

Respuesta

8

El error proviene del hecho de que no está escribiendo START_OBJECT/END_OBJECT en los pares nombre-valor/valor, por lo que debería ser fácil de corregir.

En cuanto al filtrado más dinámico, puede leer this blog entry que incluye métodos estándar. @JsonView funciona si tiene conjuntos de definiciones estáticas (una de las cuales puede seleccionar dinámicamente por base de serialización), pero si desea un sistema aún más dinámico, @JsonFilter es el camino a seguir.

Alternativamente, otra manera relativamente sencilla sería la primera "convertir" a su POJO en un mapa:

Mapa apoyos = objectMapper.convertValue (POJO, Map.class);

(que es similar a la serialización como JSON, excepto que resultado es un mapa que haría como JSON)

y luego recortar selectivamente mapa, y que a medida que serializar JSON.O, si lo prefiere, puede usar JsonNode ("modelo de árbol") como punto intermedio para modificar y luego serializar.

Cuestiones relacionadas