Saturday 15 May 2010

RestEasy, how to prevent marshalling of JAXB annotated POJOs to and from JSON -



RestEasy, how to prevent marshalling of JAXB annotated POJOs to and from JSON -

i started service consumes , produces output in json. utilize resteasy-jackson-provider (de)marshalling takes info class description. after while asked add together xml mediatype. annotated dtos jaxb annotations , added resteasy-jaxb-provider. result, observed produced json output derives jaxb annotations differs original format.

i on resteasy version 3.0.4. described utilize next providers

resteasy-jackson-provider resteasy-axb-provider. resteasy-jettison-provider, because integrated resteasy spring , provider transitive dependency.

i got aware of problem when

used xmlelementwrapper lists , when

i wrote custom xmladapter serializes complex info construction map<string, list<string>>. requests xml mediatype fine. requests json mediatype cause exception. jackson seems exploit xmladapter farther information. not case before. jackson able marshall map without jaxb annotations.

org.codehaus.jackson.map.exc.unrecognizedpropertyexception: unrecognized field "customer" (class x.y.z.optionalparametersmaptype), not marked ignorable @ [source: org.apache.catalina.connector.coyoteinputstream@77119553; line: 1, column: 131] (through reference chain: x.y.z.request["optional"]->x.y.zoptionalparametersmaptype["customer"] ) @ org.codehaus.jackson.map.exc.unrecognizedpropertyexception.from(unrecognizedpropertyexception.java:53) @ org.codehaus.jackson.map.deser.stddeserializationcontext.unknownfieldexception(stddeserializationcontext.java:267) @ org.codehaus.jackson.map.deser.std.stddeserializer.reportunknownproperty(stddeserializer.java:673) @ org.codehaus.jackson.map.deser.std.stddeserializer.handleunknownproperty(stddeserializer.java:659) @ org.codehaus.jackson.map.deser.beandeserializer.handleunknownproperty(beandeserializer.java:1365) @ org.codehaus.jackson.map.deser.beandeserializer._handleunknown(beandeserializer.java:725) @ org.codehaus.jackson.map.deser.beandeserializer.deserializefromobject(beandeserializer.java:703) @ org.codehaus.jackson.map.deser.beandeserializer.deserialize(beandeserializer.java:580) @ org.codehaus.jackson.xc.xmladapterjsondeserializer.deserialize(xmladapterjsondeserializer.java:59) @ org.codehaus.jackson.map.deser.settablebeanproperty.deserialize(settablebeanproperty.java:299) @ org.codehaus.jackson.map.deser.settablebeanproperty$fieldproperty.deserializeandset(settablebeanproperty.java:579) @ org.codehaus.jackson.map.deser.beandeserializer.deserializefromobject(beandeserializer.java:697) @ org.codehaus.jackson.map.deser.beandeserializer.deserialize(beandeserializer.java:580) @ org.codehaus.jackson.map.objectmapper._readvalue(objectmapper.java:2704) @ org.codehaus.jackson.map.objectmapper.readvalue(objectmapper.java:1315) @ org.codehaus.jackson.jaxrs.jacksonjsonprovider.readfrom(jacksonjsonprovider.java:419)

so, how can prevent resteasy using jaxb annotations marshalling , json?

here request class:

@xmlaccessortype(xmlaccesstype.field) @xmlrootelement(name = "domainrecommendationrequest") public class request { @xmljavatypeadapter(optionalparametersxmladapter.class) private map<string, list<string>> optional = new hashmap<>(); }

here xmladapter:

@override public class optionalparametersxmladapter extends xmladapter<optionalparametersmaptype, map<string, list<string>>> { public optionalparametersmaptype marshal(map<string, list<string>> v) throws exception { optionalparametersmaptype result = new optionalparametersmaptype(); list<optionalparameteritemtype> optionalparameteritemtypes = new arraylist<>(); set<string> keyset = v.keyset(); (string parametername : keyset) { optionalparameteritemtype item = new optionalparameteritemtype(); item.name = parametername; item.values = v.get(parametername); optionalparameteritemtypes.add(item); } result.parameter = optionalparameteritemtypes; homecoming result; } }

here wrapper map:

public class optionalparametersmaptype { public list<optionalparameteritemtype> parameter = new arraylist<>(); }

here actual map entry item:

public class optionalparameteritemtype { @xmlattribute public string name; @xmlelementwrapper(name = "values") @xmlelement(name = "value") public list<string> values = new arraylist<>(); }

this expect in json request:

{"optional":{"customer":["mike"]}}

as can see, intend have different format in xml.

the problem resteasy-jackson-provider depends on jackson-module-jaxb-annotations, used map jaxb annotations/annotated classes json. in normal explicit utilize of objectmapper, in order create utilize of module, need explicitly register module (see here)

objectmapper objectmapper = new objectmapper(); jaxbannotationmodule module = new jaxbannotationmodule(); objectmapper.registermodule(module); -- or -- annotationintrospector introspector = new jaxbannotationintrospector(); objectmapper.setannotationintrospector(introspector);

that beingness said, appears (not confirmed facts, looks probable) when objectmapper beingness created serialization, when jaxb annotations noticed, module automatically registered.

i don't know of possible annotations can utilize stop this, 1 way solve problem create contextresolver objectmapper, don't register jaxb module.

@provider public class objectmappercontextresolver implements contextresolver<objectmapper> { @override public objectmapper getcontext(class<?> type) { homecoming new objectmapper(); } }

once register our jax-rs application, context resolver used objectmapper. configure objectmapper further, example. test , works expected.

json jaxb jax-rs marshalling resteasy

No comments:

Post a Comment