没有字符串参数的构造函数/工厂方法可以从整数值反序列化字符串。

4

我正在尝试将以下XML反序列化为对象:

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

我的课程如下

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;
}
}

我的 mapper 依赖如下:

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

以下是出现异常并由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')

在 [源代码:out/test/resources/test.xml; 行:4,列:16] 处发生异常(通过引用链:service.Foo["dean"]->service.Dean["bar"]->java.util.ArrayList[0])

从异常信息中看来,映射器将值28视为字符串而不是整数,但如果我将Bar类更改为以下内容,并向原始xml元素bar添加一个属性,则相同的测试将通过。

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));
}

我认为Mapper应该从构造函数参数类型推断出类型,并尝试使用字符串值实例化该对象,在底层执行类似于Integer.valueOf(“28”)的操作。


如果从 Bar 构造函数中删除参数,它将正常工作。 - Andreas
但这意味着您需要使类成为不可变的,这并不是期望的。 - Dean Smith
我的意思是可变的,抱歉! - Dean Smith
1个回答

3

为POJO添加空构造函数,并为所有字段添加。也可以尝试以下操作:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接