gpt4 book ai didi

java - 当@JacksonXmlProperty.localName 匹配@JacksonXmlRootElement.localName 时无法反序列化展开的列表

转载 作者:行者123 更新时间:2023-11-30 07:12:02 26 4
gpt4 key购买 nike

好吧, friend 们……我很难理解这个问题。我有一个表示类型 XmlTest 的 XML 文档. XmlTest有一个属性children类型 List<XmlTest> . children是一个未包装的 XML 集合。

问题是,当我将 XML 源反序列化为 XmlTest 时它失败的实例:gist

java.lang.IllegalStateException: Current state not XML_START_ELEMENT (1) but 6
at com.fasterxml.jackson.dataformat.xml.deser.XmlTokenStream.repeatStartElement(XmlTokenStream.java:228)
at com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser.addVirtualWrapping(FromXmlParser.java:280)
at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer._configureParser(WrapperHandlingDeserializer.java:140)
at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:108)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:230)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:207)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:464)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:376)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:977)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:109)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
at a.test.utilities.XmlHelpers.fromXml(XmlHelpers.java:19)
at a.UnitTest.test(UnitTest.java:22)

这是我正在使用的 XML 文档:gist

<test 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>
</test>

这是我用来引发异常的单元测试:gist

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

}

如何将此 XML 文档反序列化为 XmlTest实例?

编辑 1

我发现更改 XML 文档中根元素的名称将导致反序列化成功。这是一个有趣的行为,但不是我的选择,我不控制我的应用程序中文档的构造。

这将按预期进行反序列化:gist

<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=[]}]}]}

关于java - 当@JacksonXmlProperty.localName 匹配@JacksonXmlRootElement.localName 时无法反序列化展开的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20673153/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com