Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically ignore properties with JacksonJson

I'm aware that there are multiple way to tell JacksonJson to ignore properties during rendering but all of them are static. (JasonIgnore, MixIn classes, ..).

This is my scenario. A domain object can implement a interface called FilteredDomain to allow it to be dynamically filtered. The interface is simple and only exposes one method "getIgnoreProperties". (A list of properties to ignore).

I then register a Custom Serializer that binds to the FilteredDomain object. The code looks something like:

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

First, I really dislike that I need to use the Spring Bean wrapper to get a list of all properties and iterate through them (There must be a way to do this is jackson json).

Second, The code still dosen't work. I get the error:

org.codehaus.jackson.JsonGenerationException: Can not write a field name, expecting a value at org.codehaus.jackson.impl.JsonGeneratorBase._reportError(JsonGeneratorBase.java:480) at org.codehaus.jackson.impl.Utf8Generator.writeFieldName(Utf8Generator.java:270) at org.codehaus.jackson.JsonGenerator.writeObjectField(JsonGenerator.java:1088) at com.rootmusic.util.SystemJsonObjectMapper$ValueObjectSerializer.serialize(SystemJsonObjectMapper.java:65) at com.rootmusic.util.SystemJsonObjectMapper$ValueObjectSerializer.serialize(SystemJsonObjectMapper.java:1) at org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:304) at org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:254) at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:142) at org.codehaus.jackson.map.ser.MapSerializer.serializeFields(MapSerializer.java:287) at 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) at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:280)

like image 653
Tobias Avatar asked Aug 12 '11 09:08

Tobias


People also ask

How do I ignore JSON property based on condition?

To ignore individual properties, use the [JsonIgnore] attribute. You can specify conditional exclusion by setting the [JsonIgnore] attribute's Condition property. The JsonIgnoreCondition enum provides the following options: Always - The property is always ignored.

How do you ignore certain fields based on a serializing object to JSON?

If there are fields in Java objects that do not wish to be serialized, we can use the @JsonIgnore annotation in the Jackson library. The @JsonIgnore can be used at the field level, for ignoring fields during the serialization and deserialization.

How do I ignore properties in ObjectMapper?

ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); objectMapper. configure(DeserializationFeature. FAIL_ON_UNKNOWN_PROPERTIES, false); This will now ignore unknown properties for any JSON it's going to parse, You should only use this option if you can't annotate a class with @JsonIgnoreProperties annotation.


1 Answers

The error comes from the fact that you are not writing START_OBJECT / END_OBJECT around field-name/value pairs, so that should be easy to fix.

As to more dynamic filtering, you could read this blog entry which includes standard methods. @JsonView works if you have sets of static definitions (one of which you can dynamically select on per-serialization basis), but if you want yet more dynamic system, @JsonFilter is the way to go.

Alternatively, another relatively simple way would be to first "convert" your POJO into a Map:

Map props = objectMapper.convertValue(pojo, Map.class);

(which is similar to serializing it as JSON, except that result is a Map which would render as JSON)

and then selectively trim Map, and serialize that as JSON. Or, if you prefer, you can use JsonNode ("tree model") as the intermediate thing to modify and then serialize.

like image 143
StaxMan Avatar answered Oct 19 '22 23:10

StaxMan