No string constructor / factory constructor to deserialize from String value when it's an integer

I am trying to deserialize the following xml into objects:

<?xml version="1.0" encoding="iso-8859-1" ?>
   <foo>
     <dean>
      <bar>28</bar>
      <bar>31</bar>
    </dean>
  </foo>

      

My classes are as follows

public class Foo {

private final Dean dean;

public Foo(@JacksonXmlProperty(localName = "dean") final Dean dean) {
    this.dean = dean;
}

public Dean getDean() {
    return dean;
}
}

public class Dean {

@JacksonXmlElementWrapper(useWrapping = false)
private final List<Bar> bar;

public Dean(@JacksonXmlProperty(localName = "bar") final List<Bar> bar) {
    this.bar = bar;
}

public List<Bar> getBar() {
    return bar;
}
}

public class Bar {

@JacksonXmlText
private Integer value;

public Bar(@JacksonXmlProperty(localName = " ") Integer value) {
    this.value = value;
}


public Integer getValue() {
    return value;
}
}

      

My crankcase dependencies are as follows:

gradle
ext {
jacksonVersion = "2.8.9"

      

}

compile(group: "com.fasterxml.jackson.dataformat", name: "jackson-dataformat-
xml", version: "$jacksonVersion")
compile(group: "com.fasterxml.jackson.datatype", name: "jackson-datatype-
jsr310", version: "$jacksonVersion")enter code here

      

Here is a failed test with an exception that is called by the xmlMapper

@Test
public void shouldParseAndCreateObject() throws Exception {
    final JacksonXmlModule jacksonXmlModule = new JacksonXmlModule();
     XmlMapper xmlMapper = (XmlMapper) new XmlMapper(jacksonXmlModule)
            .disable(FAIL_ON_UNKNOWN_PROPERTIES, FAIL_ON_IGNORED_PROPERTIES);
    Foo foo = xmlMapper.readValue("<?xml version=\"1.0\" encoding=\"iso-8859-
1\" ?>\n" +
            "<foo>\n" +
            "    <dean>\n" +
            "        <bar>28</bar>\n" +
            "        <bar>31</bar>\n" +
            "    </dean>\n" +
            "</foo>", Foo.class);
    assertThat(foo.getDean().getBar().get(0).getValue(), is(28));
}

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of Bar: no String-argument constructor/factory method to deserialize from String value ('28')

      

in [Source: out / test / resources / test.xml; line: 4, column: 16] (via the link chain: service.Foo ["dean"] → service.Dean ["bar"] → java.util.ArrayList [0])

From reading the exception, it looks like the handler is treating the value 28 as a string and not an integer, but if I change the Bar class to the following and add an attribute on the element string to the raw xml, the same test passes.

public class Bar {

private String test;

@JacksonXmlText
private Integer value;

public Bar(@JacksonXmlProperty(localName = "test", isAttribute = true) String 
test, @JacksonXmlProperty(localName = " ") Integer value) {
    this.test = test;
    this.value = value;
}

public String getTest() {
    return test;
}

public Integer getValue() {
    return value;
}

<?xml version="1.0" encoding="iso-8859-1" ?>
<foo>
<dean>
    <bar test="haha1">28</bar>
    <bar test="haha2">31</bar>
</dean>
</foo>

@Test
public void shouldParseAndCreateObject() throws Exception {
    final JacksonXmlModule jacksonXmlModule = new JacksonXmlModule();
     XmlMapper xmlMapper = (XmlMapper) new XmlMapper(jacksonXmlModule)
            .disable(FAIL_ON_UNKNOWN_PROPERTIES, FAIL_ON_IGNORED_PROPERTIES);
    Foo foo = xmlMapper.readValue("<?xml version=\"1.0\" encoding=\"iso-8859-
1\" ?>\n" +
            "<foo>\n" +
            "    <dean>\n" +
            "        <bar test=\"haha1\">28</bar>\n" +
            "        <bar test=\"haha2\">31</bar>\n" +
            "    </dean>\n" +
            "</foo>" +
            "</foo>", Foo.class);
    assertThat(foo.getDean().getBar().get(0).getValue(), is(28));
}

      

I would say that Mapper should infer the type from the type of the constructor parameter and try to instantiate that object with a string value and under the hood do something like Integer.valueOf ("28")

+3


source to share


1 answer


Add empty constructor to POJO and also for all fields. Also try this:



JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
XmlMapper xmlMapper = new XmlMapper(module);

      

+1


source







All Articles