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)
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.
精彩评论