Java 当@JacksonXmlProperty.localName与@JacksonXmlRootElement.localName匹配时,无法反序列化展开的列表
好吧,朋友们。。。我很难在这件事上下定决心。我有一个XML文档,表示类型Java 当@JacksonXmlProperty.localName与@JacksonXmlRootElement.localName匹配时,无法反序列化展开的列表,java,serialization,jackson,deserialization,Java,Serialization,Jackson,Deserialization,好吧,朋友们。。。我很难在这件事上下定决心。我有一个XML文档,表示类型XmlTestXmlTest具有类型为List的属性childrenchildren是一个未包装的XML集合 问题是,当我将XML源反序列化为XmlTest实例时,它会失败: 以下是我正在使用的XML文档: 如果您编写自定义反序列化程序,则可以正常工作 package api.core.jasper; import java.io.IOException; import java.util.List; import or
XmlTest
XmlTest
具有类型为List
的属性children
children
是一个未包装的XML集合
问题是,当我将XML源反序列化为XmlTest
实例时,它会失败:
以下是我正在使用的XML文档:
如果您编写自定义反序列化程序,则可以正常工作
package api.core.jasper;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
public class UnitTest {
@Test
public void test() throws Exception {
final ObjectMapper mapper = new XmlMapper();
final XmlTest before =
new XmlTest("0", Lists.newArrayList(new XmlTest("0.1", null),
new XmlTest("0.2", Lists.newArrayList(new XmlTest("0.2.1", null)))));
System.out.println(before);
final String xml = mapper.writeValueAsString(before);
System.out.println(xml);
final XmlTest after = mapper.readValue(xml, XmlTest.class);
System.out.println(after);
}
@JsonDeserialize(using = XmlTestDeserializer.class)
@JacksonXmlRootElement(localName = "test")
public static class XmlTest {
@JacksonXmlProperty(localName = "id", isAttribute = true)
public String id;
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "test")
public List<XmlTest> children;
public XmlTest(final String id, final List<XmlTest> children) {
this.id = id;
this.children = Optional.fromNullable(children).or(Lists.<XmlTest>newArrayList());
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("id", id)
.add("children", children)
.toString();
}
}
public static class XmlTestDeserializer extends StdDeserializer<XmlTest> {
protected XmlTestDeserializer() {
super(XmlTest.class);
}
@Override
public XmlTest deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
JsonProcessingException {
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw new IOException("Invalid token, expected START_OBJECT");
}
String id = null;
final List<XmlTest> children = Lists.newArrayList();
while (jp.nextToken() != JsonToken.END_OBJECT) {
final String key = jp.getCurrentName();
jp.nextToken();
if ("id".equals(key)) {
id = jp.readValueAs(String.class);
} else if ("test".equals(key)) {
final XmlTest child = jp.readValueAs(XmlTest.class);
if (child != null) {
children.add(child);
}
}
}
jp.close();
return new XmlTest(id, children);
}
}
}
包api.core.jasper;
导入java.io.IOException;
导入java.util.List;
导入org.junit.Test;
导入com.fasterxml.jackson.core.JsonParser;
导入com.fasterxml.jackson.core.JsonProcessingException;
导入com.fasterxml.jackson.core.JsonToken;
导入com.fasterxml.jackson.databind.DeserializationContext;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.annotation.JsonDeserialize;
导入com.fasterxml.jackson.databind.desr.std.StdDeserializer;
导入com.fasterxml.jackson.dataformat.xml.XmlMapper;
导入com.fasterxml.jackson.dataformat.xml.annotation.jacksonxmlementwrapper;
导入com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
导入com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
导入com.google.common.base.Objects;
导入com.google.common.base.Optional;
导入com.google.common.collect.list;
公共类单元测试{
@试验
public void test()引发异常{
final ObjectMapper mapper=new XmlMapper();
前的最终测试=
新的XmlTest(“0”,列出.newArrayList(新的XmlTest(“0.1”,空),
新的XmlTest(“0.2”,Lists.newArrayList(新的XmlTest(“0.2.1”,null‘)’);
系统输出打印项次(之前);
最后一个字符串xml=mapper.writeValueAsString(之前);
System.out.println(xml);
final XmlTest after=mapper.readValue(xml,XmlTest.class);
系统输出打印项次(后);
}
@JsonDeserialize(使用=XmlTestDeserializer.class)
@JacksonXmlRootElement(localName=“test”)
公共静态类XmlTest{
@JacksonXmlProperty(localName=“id”,isAttribute=true)
公共字符串id;
@JacksonXmlElementWrapper(useWrapping=false)
@JacksonXmlProperty(localName=“test”)
公开儿童名单;
公共XmlTest(最终字符串id,最终列表子项){
this.id=id;
this.children=可选.fromNullable(children).或(Lists.newArrayList());
}
@凌驾
公共字符串toString(){
返回Objects.toStringHelper(this)
.add(“id”,id)
.添加(“儿童”,儿童)
.toString();
}
}
公共静态类XmlTestDeserializer扩展StdDeserializer{
受保护的XmlTestDeserializer(){
super(XmlTest.class);
}
@凌驾
公共XmlTest反序列化(最终JsonParser jp,最终反序列化上下文ctxt)引发IOException,
JsonProcessingException{
if(jp.getCurrentToken()!=JsonToken.START\u对象){
抛出新IOException(“无效令牌,应为START_对象”);
}
字符串id=null;
final List children=Lists.newArrayList();
while(jp.nextToken()!=JsonToken.END\u对象){
最终字符串键=jp.getCurrentName();
jp.nextToken();
如果(“id”。等于(键)){
id=jp.readValueAs(String.class);
}否则,如果(“测试”。等于(键)){
最终XmlTest子级=jp.readValueAs(XmlTest.class);
if(child!=null){
添加(child);
}
}
}
jp.close();
返回新的XmlTest(id,children);
}
}
}
测试控制台输出:
XmlTest{id=0, children=[XmlTest{id=0.1, children=[]}, XmlTest{id=0.2, children=[XmlTest{id=0.2.1, children=[]}]}]}
<test id="0"><test id="0.1"/><test id="0.2"><test id="0.2.1"/></test></test>
XmlTest{id=0, children=[XmlTest{id=0.1, children=[]}, XmlTest{id=0.2, children=[XmlTest{id=0.2.1, children=[]}]}]}
XmlTest{id=0,children=[XmlTest{id=0.1,children=[]},XmlTest{id=0.2,children=[XmlTest{id=0.2.1,children=[]}]
XmlTest{id=0,children=[XmlTest{id=0.1,children=[]},XmlTest{id=0.2,children=[XmlTest{id=0.2.1,children=[]}]}
我已尝试使用您的示例代码。看起来像是jackson数据格式xml中的一个bug。@EugeneEvdokimov,我同意我今天提交了这个bug
package api.core.jasper;
import static org.junit.Assert.fail;
import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.google.common.collect.Lists;
public class UnitTest {
@Test
public void test() throws Exception {
final ObjectMapper mapper = new XmlMapper();
final XmlTest before =
new XmlTest("0", Lists.newArrayList(new XmlTest("0.1", null),
new XmlTest("0.2", Lists.newArrayList(new XmlTest("0.2.1", null)))));
final String xml = mapper.writeValueAsString(before);
final XmlTest after = mapper.readValue(xml, XmlTest.class);
fail();
}
@JacksonXmlRootElement(localName = "test")
public static class XmlTest {
private final String id;
private final List<XmlTest> children;
@JsonCreator
public XmlTest(@JsonProperty("id") final String id, @JsonProperty("tests") final List<XmlTest> children) {
this.id = id;
this.children = children;
}
@JsonProperty("id")
@JacksonXmlProperty(localName = "id", isAttribute = true)
public String id() {
return id;
}
@JsonProperty("children")
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "test")
public List<XmlTest> children() {
return children;
}
}
}
<root id="0">
<test id="0.1">
<test id="0.1.1" />
</test>
<test id="0.2" />
<test id="0.3">
<test id="0.3.1" />
</test>
</root>
package api.core.jasper;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
public class UnitTest {
@Test
public void test() throws Exception {
final ObjectMapper mapper = new XmlMapper();
final XmlTest before =
new XmlTest("0", Lists.newArrayList(new XmlTest("0.1", null),
new XmlTest("0.2", Lists.newArrayList(new XmlTest("0.2.1", null)))));
System.out.println(before);
final String xml = mapper.writeValueAsString(before);
System.out.println(xml);
final XmlTest after = mapper.readValue(xml, XmlTest.class);
System.out.println(after);
}
@JsonDeserialize(using = XmlTestDeserializer.class)
@JacksonXmlRootElement(localName = "test")
public static class XmlTest {
@JacksonXmlProperty(localName = "id", isAttribute = true)
public String id;
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "test")
public List<XmlTest> children;
public XmlTest(final String id, final List<XmlTest> children) {
this.id = id;
this.children = Optional.fromNullable(children).or(Lists.<XmlTest>newArrayList());
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("id", id)
.add("children", children)
.toString();
}
}
public static class XmlTestDeserializer extends StdDeserializer<XmlTest> {
protected XmlTestDeserializer() {
super(XmlTest.class);
}
@Override
public XmlTest deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
JsonProcessingException {
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw new IOException("Invalid token, expected START_OBJECT");
}
String id = null;
final List<XmlTest> children = Lists.newArrayList();
while (jp.nextToken() != JsonToken.END_OBJECT) {
final String key = jp.getCurrentName();
jp.nextToken();
if ("id".equals(key)) {
id = jp.readValueAs(String.class);
} else if ("test".equals(key)) {
final XmlTest child = jp.readValueAs(XmlTest.class);
if (child != null) {
children.add(child);
}
}
}
jp.close();
return new XmlTest(id, children);
}
}
}
XmlTest{id=0, children=[XmlTest{id=0.1, children=[]}, XmlTest{id=0.2, children=[XmlTest{id=0.2.1, children=[]}]}]}
<test id="0"><test id="0.1"/><test id="0.2"><test id="0.2.1"/></test></test>
XmlTest{id=0, children=[XmlTest{id=0.1, children=[]}, XmlTest{id=0.2, children=[XmlTest{id=0.2.1, children=[]}]}]}