Deserialization issue from XML to POJO with Jackson: no String-argument constructor/factory method t

3,163 views
Skip to first unread message

Mindaugas Vezelis

unread,
Jan 5, 2017, 9:06:24 AM1/5/17
to jackson-user, mind...@stunn.co.uk
I've got an XML document which I need to convert (deserialize) into Java POJO. I cannot change the structure of the XML document. I use Java 8, and Jackson framework for mapping. Gradle dependencies:
dependencies { compile('com.fasterxml.jackson.dataformat:jackson-dataformat-xml') compile('org.springframework.boot:spring-boot-starter-freemarker') compile('org.springframework.boot:spring-boot-starter-web') providedRuntime('org.springframework.boot:spring-boot-starter-tomcat') testCompile('org.springframework.boot:spring-boot-starter-test') }



Wrapper XML Doc:

@JacksonXmlRootElement(localName = "rates_response") public class RatesResponse implements Serializable{ private static final long serialVersionUID = 3254688495454519L; @JacksonXmlProperty(isAttribute = true) private String b_number = ""; @JacksonXmlProperty(isAttribute = true) private String l_premium = ""; @JacksonXmlProperty(isAttribute = true) private String currency = ""; @XmlElement(required = false) @JacksonXmlProperty private String c_b_relationship = null; @JacksonXmlProperty(isAttribute = true) private String n_of_p_loans = null; /* * Key: status_code * Key: status_explanation */ @JacksonXmlElementWrapper private Map<String, String> message_status = null; // @XmlElement @JacksonXmlElementWrapper(useWrapping = false) private List<RateDetails> rate_details = null; public RatesResponse(){} //GETTERS/SETTERS




 Child document (`
List<RateDetails> rate_details = null;

`
):
@JacksonXmlRootElement(localName = "rate_details") public class RateDetails implements Serializable { private static final long serialVersionUID = 324564684815158619L; @JacksonXmlProperty private String r_reference = null; @JacksonXmlProperty private String n_of_p_days = null; @JacksonXmlProperty private String n_of_instalments = null; @JacksonXmlProperty private String n_rate = null; @JacksonXmlProperty private String p_p_available = null; @XmlElement(required = false) @JacksonXmlProperty private String i_overrider = null;//not always appears in doc @JacksonXmlProperty private String a_fee = null; @JacksonXmlProperty private String m_fee = null; @JacksonXmlProperty private String t_fees = null; @JacksonXmlProperty private String t_c_for_credit = null; @JacksonXmlProperty private String d_amount = null; @JacksonXmlProperty private String apr = null; public RateDetails(){} //GETTERS/SETTERS



XML document to parse:

<?xml version="1.0"?> <!DOCTYPE rates_response SYSTEM "p_f_interface.dtd"> <rates_response b_number="KK5000000000" l_premium="5000.00" currency="GBP" > <message_status> <status_code>1000</status_code> <status_explanation>Success</status_explanation> </message_status> <c_b_relationship n_of_p_loans="0"/> <rate_details> <r_reference>AS28</r_reference> <n_of_p_days>28</n_of_p_days> <n_of_instalments>12</n_of_instalments> <n_rate>7.00</n_rate> <p_p_available>NO</p_p_available> <i_overrider>3.65</i_overrider> <a_fee>0.00</a_fee> <m_fee>0.00</m_fee> <t_fees>0.00</t_fees> <t_c_for_credit>350.00</t_c_for_credit> <d_amount>0.00</d_amount> <apr>16.05</apr> </rate_details> </rates_response>



The method which parses the doc:
private RatesResponse readRatesDoc() { RatesResponse xmlContainer = null; ObjectMapper xmlMapper = new XmlMapper(); try { xmlContainer = xmlMapper.readValue(contrUtil.readXmlFile("Rates_Response.xml"), RatesResponse.class); } catch (IOException e) { log.log(Level.SEVERE, "An Exception on parsing XML document", e); } return xmlContainer; }



The exception:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of premium.finance.beanResponse.rates.RateDetails: no String-argument constructor/factory method to deserialize from String value ('16.05') at [Source: java.io.StringReader@7bd22d0b; line: 1, column: 945] (through reference chain: premium.finance.beanResponse.rates.RatesResponse["rate_details"]->java.util.ArrayList[1]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:261) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:366) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:307) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1278) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:159) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:277) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:249) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:120) ~[jackson-dataformat-xml-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789) ~[jackson-databind-2.8.3.jar:2.8.3] at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833) ~[jackson-databind-2.8.3.jar:2.8.3] at premium.finance.controller.IndexController.readRatesDoc(IndexController.java:190) [main/:na] at premium.finance.controller.IndexController.requestIndex(IndexController.java:69) [main/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410) [tomcat-embed-core-8.5.5.jar:8.5.5] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.5.jar:8.5.5] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_91] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_91] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.5.jar:8.5.5] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]



The top line says:

no String-argument constructor/factory method to deserialize from String value ('16.05')

The value it is referring to comes from under this tag:

<apr>16.05</apr>

If I displace (move around) the tag,

<apr>16.05</apr>

, the parser works and no exception gets caused. If I replace the tag by different tag, the same exception still occurs; it affects only the last tag within the <rate_details> wrapper tag, for some reasons.

What the problem can be?



Tatu Saloranta

unread,
Jan 6, 2017, 10:14:51 AM1/6/17
to jackson-user, mind...@stunn.co.uk
Hi Mindaugas. This sounds like a potential bug. 
Could you file the issue at 


including all the information from above (thank you for including so much relevant information here!).
The reason I am asking this is two-fold: for one, it's easier to keep track of it (so we don't forget to look into it when we get a chance), and it is also bit easier to read with github markdown formatting.

As to the root cause I can only say that there have been issues like this in the past, related to `List` elements; and sometimes handling of first element and following ones is slightly different at low level, related to necessary structural changes between XML and JSON. So it is not entirely surprising that problems only occur with multiple-element lists.

-+ Tatu +-



--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user+unsubscribe@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages