-
Notifications
You must be signed in to change notification settings - Fork 114
JacksonSampleCustomViewProcessing
Paul Brown edited this page Oct 19, 2011
·
2 revisions
(contributed by Andrei Voden)
(copied verbatim from the mailing list)
"Hi. Instead of using class-type filtering I would like to do instance-based one. For example I have classes:
class A {
String name;
B info;
A child;
}
class B {
int distance;
String id;
}
A root = new A();Now, I would like to serialize instance root in a following way: serialize all fields that belong to the root but for root.child serialize only name. So result would be:
"root": {
"name": "somthing",
"info": { "distance":100, "id":"123"},
"child": {"name": "lalala"}
}... Any ideas whats the easiest way to pass filtering object along during serialization? Filtering object will probably Map object. "
And here is eventual code written to achieve custom configurable property filtering for serialization:
public class CustomSerializationView
{
static class ViewBean
{
public String name;
public String value;
public String secret;
public ViewBean sibling;
public ViewBeanChild child;
public ViewBean(String name, String value, String secret) {
this.name = name;
this.value = value;
this.secret = secret;
child = new ViewBeanChild();
}
}
static class ViewBeanChild
{
public long id = 123;
public String name = "child";
public String address = "123 Street";
}
static class FilteredWriter
extends BeanPropertyWriter
{
public FilteredWriter(BeanPropertyWriter w) {
super(w);
}
public void serializeAsField(Object bean, JsonGenerator jgen,
SerializerProvider prov)
throws Exception
{
BzStdSerializerProvider myprov = (BzStdSerializerProvider)prov;
HashMap filter = myprov.getCurrentFilter();
if (filter == null) {
super.serializeAsField(bean, jgen, prov);
} else if (filter.containsKey(this._name)) {
Object subfilter = filter.get(this._name);
myprov.pushFilter(HashMap.class.isAssignableFrom(subfilter.getClass())
? (HashMap)subfilter : null);
super.serializeAsField(bean, jgen, prov);
myprov.popFilter();
}
}
}
public static class CustomBeanFactory
extends CustomSerializerFactory
// (CSF extends BeanSerializerFactory)
{
@Override
protected BeanSerializer processViews(SerializationConfig
config, BasicBeanDescription beanDesc,
BeanSerializer ser,
List<BeanPropertyWriter> props)
{
ser = super.processViews(config, beanDesc, ser, props);
BeanPropertyWriter[] writers = props.toArray(new
BeanPropertyWriter[props.size()]);
for (int i = 0; i < writers.length; ++i) {
writers[i] = new FilteredWriter (writers[i]);
}
ser = ser.withFiltered(writers);
return ser;
}
}
static class BzStdSerializerProvider extends StdSerializerProvider {
private HashMap _filter;
private Vector<HashMap> _stack = new Vector();
public BzStdSerializerProvider() {
super();
}
public BzStdSerializerProvider(HashMap filter) {
super();
_filter = filter;
}
protected BzStdSerializerProvider(SerializationConfig config,
StdSerializerProvider src, SerializerFactory f) {
super (config, src, f);
}
protected BzStdSerializerProvider(SerializationConfig config,
StdSerializerProvider src, SerializerFactory f, HashMap filter) {
super (config, src, f);
_filter = filter;
}
protected StdSerializerProvider
createInstance(SerializationConfig config, SerializerFactory jsf)
{
return new BzStdSerializerProvider (config, this, jsf, _filter);
}
public HashMap getCurrentFilter () {
if (_stack.isEmpty()) return _filter;
return _stack.lastElement();
}
public void pushFilter (HashMap filter) {
_stack.add(filter);
}
public void popFilter () {
if (!_stack.isEmpty()) {
_stack.removeElement(_stack.lastElement());
}
}
}
public static void main(String[] args) throws Exception
{
// create dummy objects
ViewBean bean = new ViewBean("mr bean", "goofy", "secret!");
bean.sibling = new ViewBean("sibling", "lala", "boooo");
// create filtering Map
String filter = "{\"name\":0,\"value\":0,
\"sibling\":{\"name\":0}, \"child\":{\"id\":0,\"address\":0}}";
ObjectMapper filterMapper = new ObjectMapper();
HashMap filterMap = filterMapper.readValue(filter, HashMap.class);
// custom mapper
ObjectMapper mapper = new ObjectMapper(null, new
BzStdSerializerProvider(filterMap), null);
mapper.setSerializerFactory(new CustomBeanFactory());
// First, without enabling view handling:
System.out.println("With default serializer:
"+mapper.writeValueAsString(bean));
String json = mapper.viewWriter(String.class).writeValueAsString(bean);
System.out.println("With custom serializer: "+json);
}CategoryJackson