2011-08-12 16 views
8

Jestem świadomy, że istnieje wiele sposobów, aby powiedzieć JacksonJsonowi, aby ignorował właściwości podczas renderowania, ale wszystkie z nich są statyczne. (JasonIgnore, klasy MixIn ..).Dynamicznie ignoruj ​​właściwości za pomocą JacksonJson

Oto mój scenariusz. Obiekt domeny może implementować interfejs o nazwie FilteredDomain do , umożliwiający dynamiczne filtrowanie. Interfejs jest prosty i ujawnia tylko jedną metodę "getIgnoreProperties". (Lista właściwości, które należy zignorować).

Następnie rejestruję niestandardowy serializer, który wiąże obiekt FilteredDomain. Kod wygląda mniej więcej tak:

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

Po pierwsze, ja naprawdę lubię, że muszę użyć opakowania Wiosna Bean aby uzyskać listę wszystkich właściwości i iterację nich (Musi być jakiś sposób, aby to zrobić jest jackson json).

Po drugie, kod nadal nie działa. I pojawia się błąd:

org.codehaus.jackson.JsonGenerationException: nie można zapisać nazwę pola, oczekując wartość na org.codehaus.jackson.impl.JsonGeneratorBase._reportError (JsonGeneratorBase.java:480) w org .codehaus.jackson.impl.Utf8Generator.writeFieldName (Utf8Generator.java:270) na org.codehaus.jackson.JsonGenerator.writeObjectField (JsonGenerator.java:1088) na com.rootmusic.util.SystemJsonObjectMapper $ ValueObjectSerializer.serialize (SystemJsonObjectMapper .java: 65) na com.rootmusic.util.SystemJsonObjectMapper $ ValueObjectSerializer.serialize (SystemJsonObjectMapper.java:1) na org.codehaus.jackson.map.ser.ContainerSerializers $ IndexedListSerializer.serializeContents (ContainerSe rializers.java:304) w org.codehaus.jackson.map.ser.ContainerSerializers $ IndexedListSerializer.serializeContents (ContainerSerializers.java:254) at org.codehaus.jackson.map.ser.ContainerSerializers $ AsArraySerializer.serialize (ContainerSerializers. java: 142) w org.codehaus.jackson.map.ser.MapSerializer.serializeFields (MapSerializer.java:287) w org.codehaus.jackson.map.ser.MapSerializer.serialize (MapSerializer.java:212) at org.codehaus.jackson.map.ser.MapSerializer.serialize (MapSerializer.java:23) at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue (StdSerializerProvider.java:606) w org.codehaus.jackson. map.ser.StdSerializerProvider.serializeValue (StdSerializerProvider.java:280)

Odpowiedz

8

Błąd wynika z faktu, że nie piszesz START_OBJECT/END_OBJECT wokół par nazwa-wartość/wartość, więc powinno to być łatwe do naprawienia.

Jeśli chodzi o filtrowanie dynamiczne, można przeczytać this blog entry, który zawiera standardowe metody. @JsonView działa, jeśli masz zestawy definicji statycznych (z których jedno możesz dynamicznie wybierać na podstawie serializacji), ale jeśli chcesz jeszcze bardziej dynamicznego systemu, @JsonFilter jest drogą do zrobienia.

Ewentualnie inny stosunkowo prosty sposób byłoby najpierw "przerobić" swoje POJO na mapie:

Mapa rekwizyty = objectMapper.convertValue (Pojo, Map.class);

(który jest podobny do szeregowania jako JSON, z wyjątkiem tego wyniku jest mapą które powodowałyby w JSON)

i następnie selektywnie wykończenia mapie, a serializacji że JSON.Lub, jeśli wolisz, możesz użyć JsonNode ("model drzewa") jako obiektu pośredniego do modyfikacji, a następnie serializacji.

Powiązane problemy