java - Jackson ignores xml root element for abstract class -
i migrating application jersey spring mvc , i'm having problems make jackson work legacy xml's. receive abstract object on request body follow
mycontroller.java
@requestmapping(method = requestmethod.put, value = connectorconstants.subscribe_key) public callable<subscriberesult> subscribe( @pathvariable final string userkey, @requestbody(required = false) final subscriberequest subscriberequest) { return new callable<subscriberesult>() { @override public subscriberesult call() throws exception { return someservice.subscribe(userkey, subscriberequest); } }; }
subscriberequest.java
@xmlrootelement(name = "subscribe_request") @xmlseealso({ onerequest.class, anotherrequest.class, simpledomainrequest.class }) public abstract class subscriberequest implements request { /* (non-javadoc) * @see com.company.client.request.request#getbody() */ @override public abstract <k, v> map<k, v> getbody(); protected final map<object, object> params = new hashmap<object, object>(); }
simpledomainrequest.java
@xmlaccessortype(xmlaccesstype.field) @xmlrootelement(name = "simple_domain_request") public class simpledomainrequest extends subscriberequest { ... methods }
anotherrequest.java
@xmlaccessortype(xmlaccesstype.field) @xmlrootelement(name = "another_request") public class anotherrequest extends subscriberequest { ... methods }
onerequest.java
@xmlaccessortype(xmlaccesstype.field) @xmlrootelement(name = "one_request") public class onerequest extends subscriberequest { ... methods }
here 1 of xml's controller receives if type of object simpledomainrequest:
<simple_domain_request> <params> <entry> <key xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xs="http://www.w3.org/2001/xmlschema" xsi:type="xs:string">my key </key> <value xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xs="http://www.w3.org/2001/xmlschema" xsi:type="xs:string">my value </value> </entry> </params> </simple_domain_request>
so except controller part different when using jersey, got code working fine, jersey controller deserializing object without problem. after migrating use spring-mvc , jackson simple can't deserialize it. read jackson doesn't support @xmlseealso tried following changes according guides found on supporting abstract class jackson:
subscriberequest
@xmlrootelement(name = "subscribe_request") @xmlseealso({ onerequest.class, anotherrequest.class, simpledomainrequest.class }) @jsontypeinfo(use = jsontypeinfo.id.name, include = jsontypeinfo.as.wrapper_object) @jsonsubtypes({ @jsonsubtypes.type(value = simpledomainrequest.class, name = "simple_domain_request"), @jsonsubtypes.type(value = anotherrequest.class, name = "another_request"), @jsonsubtypes.type(value = onerequest.class, name = "one_request") }) public abstract class subscriberequest implements request { /* (non-javadoc) * @see com.company.client.request.request#getbody() */ @override public abstract <k, v> map<k, v> getbody(); @jsonproperty protected final map<object, object> params = new hashmap<object, object>(); }
but following error jackson: could not resolve type id 'params'
caused by: com.fasterxml.jackson.databind.jsonmappingexception: not resolve type id 'params' subtype of [simple type, class com.company.subscriberequest]: known type ids = [subscriberequest, one_request, simple_domain_request, another_request] @ [source: java.io.pushbackinputstream@55416df4; line: 4, column: 13] @ com.fasterxml.jackson.databind.jsonmappingexception.from(jsonmappingexception.java:148) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.deserializationcontext.unknowntypeexception(deserializationcontext.java:948) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.jsontype.impl.typedeserializerbase._handleunknowntypeid(typedeserializerbase.java:275) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.jsontype.impl.typedeserializerbase._finddeserializer(typedeserializerbase.java:162) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.jsontype.impl.aswrappertypedeserializer._deserialize(aswrappertypedeserializer.java:100) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.jsontype.impl.aswrappertypedeserializer.deserializetypedfromobject(aswrappertypedeserializer.java:49) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.deser.abstractdeserializer.deserializewithtype(abstractdeserializer.java:131) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.deser.impl.typewrappeddeserializer.deserialize(typewrappeddeserializer.java:42) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.objectmapper._readmapandclose(objectmapper.java:3562) ~[jackson-databind-2.5.1.jar:2.5.1] @ com.fasterxml.jackson.databind.objectmapper.readvalue(objectmapper.java:2662) ~[jackson-databind-2.5.1.jar:2.5.1] @ org.springframework.http.converter.json.abstractjackson2httpmessageconverter.readjavatype(abstractjackson2httpmessageconverter.java:205) ~[spring-web-4.1.5.release.jar:4.1.5.release]
this message converters configuration:
public class webconfigurationadapter extends webmvcconfigureradapter { @override public void configuremessageconverters(list<httpmessageconverter<?>> converters) { jackson2objectmapperbuilder builder = new jackson2objectmapperbuilder(); builder.featurestoenable(mapperfeature.default_view_inclusion); converters.add(new mappingjackson2httpmessageconverter(builder.build())); converters.add(new mappingjackson2xmlhttpmessageconverter(builder.createxmlmapper(true).build())); }
if change use unwrap_root_value
builder.featurestoenable(mapperfeature.default_view_inclusion, deserializationfeature.unwrap_root_value);
then error:
caused by: com.fasterxml.jackson.databind.jsonmappingexception: root name 'params' not match expected ('subscriberequest') type [simple type, class com.company.subscriberequest]
if request body wrapped in xml tag works:
<any_name_here_doesnt_matter> <simple_domain_request> <params> <entry> <key xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xs="http://www.w3.org/2001/xmlschema" xsi:type="xs:string">my key </key> <value xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xs="http://www.w3.org/2001/xmlschema" xsi:type="xs:string">my value </value> </entry> </params> </simple_domain_request> </any_name_here_doesnt_matter>
please keep in mind thought have access subscriberequest class need mantain compatibility, can't change xml receive. default_view_inclusion there because use jsonview other objects.
i might missing obvious here appreciated or if need see more of code.
pom.xml declaring jackson
<properties> <woodstox-core-asl.version>4.4.1</woodstox-core-asl.version> <jackson.version>2.5.1</jackson.version> </properties> <!-- jackson --> <dependency> <groupid>com.fasterxml.jackson.core</groupid> <artifactid>jackson-databind</artifactid> <version>${jackson.version}</version> </dependency> <dependency> <groupid>com.fasterxml.jackson.dataformat</groupid> <artifactid>jackson-dataformat-xml</artifactid> <version>${jackson.version}</version> </dependency> <dependency> <groupid>org.codehaus.woodstox</groupid> <artifactid>woodstox-core-asl</artifactid> <version>${woodstox-core-asl.version}</version> </dependency>
spring version 4.1.5.
use @jacksonxmlrootelement(localname = "simple_domain_request"
annotation instead of @xmlrootelement(name = "simple_domain_request")
Comments
Post a Comment