java - Changing Jackson active view for a property -


using jackson, i'd able change active view when serializing property.

so, if application uses 3 views, a, b & c, might want property p type t serialize using view a, regardless if active view class null, a.class, b.class, or c.class.

i haven't found way built-in jackson, plan make own classes this.

before possibly reinvent wheel, possible normal jackson annotations and/or classes?

if not, plan following (nb: simplify question, i've omitted lot of config options & performance optimizations aren't necessary core functionality, i'll add once core works; i've omitted visibility modifiers & concision):

  1. make following annotation indicates that, annotated field or method, view should switched active view value:

    @target({field, method}) @retention(runtime) public @interface jsonapplyview {      class<?> value(); } 
  2. if @jsonapplyview applied property, somehow change value of _serializationview, getserializationview() & getactiveview() in serializerprovider original active view value @jsonapplyview (let's call jsonapplyview.value appliedview).

    if there better / more correct way change active view, please let me know.

    if correct approach, since _serializationview final, , since both getters return _serializationview, must make beanserializermodifier modifyserializer() wraps argument serializer contextualserializer with:

    jsonserializer<?> createcontextual(serializerprovider sp, beanproperty bp) {     jsonapplyview apply = bp.getannotation(jsonapplyview.class);     return         apply == null ||         apply.value().equals(sp.getactiveview()))             ?             : new viewapplyingserializer(this, apply.value())     ; } 

    viewapplyingserializer save following properties in constructor:

    final jsonserializer<?> delegate; final class<?>          appliedview; 

    viewapplyingserializer.serialize(object o, jsongenerator g, serializerprovider p) 1 of following:

    1. copy p:

      delegate.serialize(o, g, copy(p, appliedview)); 

      where serializerprovider copy(serializerprovider p, class<?> appliedview) returns copy of p _serializationview = appliedview

    2. wrap p:

      delegate.serialize(o, g, wrap(p, appliedview)); 

      where serializerprovider wrap(serializerprovider p, class<?> appliedview) returns wrapper around p _serializationview, getserializationview() & getactiveview() return appliedview

    3. use whole new objectwriter

      ow.writevalue(g, o); 

      where ow somehow obtained

i imagine copying serializerprovider best, ways i've found copy serializerprovider , change active view require passing in serializerfactory, , ways i've found serializerfactory either construct new one, or 1 objectmapper. i'd prefer use _serializerfactory current serializerprovider mimic closely possible, field protected, , haven't found getters it. easiest way copy or wrap serializerprovider make have different view class?

this has been asked long time ago looking doing similar. think great if jackson support since seems me frequent case.

for example, let have hierarchy of views, detailview (high details) inherits summaryview (low details), , 2 objects child-parent relationship. when serializing child object active detailview, might want add summary of parent , not details... need switch detailedview summaryview.

anyway, no need explain again obvious know, did modify beanserializer since while serializing beans jsonview annotation takes place.

@override public jsonserializer<?> modifyserializer(serializationconfig config, beandescription beandesc, jsonserializer<?> serializer) {     return new jsonviewoverrideserializer(serializer); } 

the jsonviewoverrideserializer keeps reference of original bean serializer. important happens in contextualization: if property not annotated @applyjsonview, return original bean serializer directly. otherwise, wraps bean serializer after contextualizing it. this:

@override public jsonserializer<?> createcontextual(serializerprovider prov, beanproperty property) throws jsonmappingexception {     jsonserializer<?> serializer = this.beanserializer;      if (serializer instanceof contextualserializer) {         serializer = ((contextualserializer) serializer).createcontextual(prov, property);     }      if (property != null) {         applyjsonview applyjsonview = property.getannotation(applyjsonview.class);          if (applyjsonview != null) {             class<?> jsonview = applyjsonview.value();                             serializer = new jsonviewoverrideserializer(serializer, jsonview);         }     }      return serializer; } 

finally, here come's tricky part want override serializerprovider object. did not found elegant way of doing neither, here's end creating new instance of serializerprovider' retrieving theserializerfactoryfrom thejsongeneratorcodec, theobjectmapper` (me have prefer retrieve provider being overridden instead well... bad can't way have access it).

public serializerprovider overrideprovider(class<?> overrideview, jsongenerator gen, serializerprovider provider) {        return ((defaultserializerprovider) provider).createinstance(provider.getconfig().withview(overrideview), ((objectmapper) gen.getcodec()).getserializerfactory(););     }); } 

(note: avoid recreating provider same active view, keep map of overridden providers in provider's attributes).

finally, have serializer effective provider before serializing object:

@override public void serialize(object value, jsongenerator gen, serializerprovider provider) throws ioexception {    serializerprovider effectiveprovider = provider;      if (provider.getactiveview() != null && overrideview != provider.getactiveview()) {                                       effectiveprovider = overrideprovider(overrideview, gen, provider);     }      beanserializer.serialize(value, gen, effectiveprovider); } 

Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -