Ich versuche, ein Paar unveränderlich POJOs erstellen Serialisierung und Deserialisierung von XML zu behandeln, die wie folgt aussieht:kann nicht gewickelte Liste mit Jackson XmlMapper deserialisieren
<?xml version="1.0" encoding="UTF-8"?>
<Outer xmlns="http://example.com">
<Foo>outer foo</Foo>
<Inners>
<Inner>
<Bar>inner 1 bar</Bar>
<Baz>inner 2 baz</Baz>
</Inner>
<Inner>
<Bar>inner 2 bar</Bar>
<Baz>inner 2 baz</Baz>
</Inner>
</Inners>
</Outer>
Ich muß serialisiert werden können, und deserialisieren sowohl eine Outer
, die eine Liste von Inner
s enthält, als auch eine Inner
für sich.
Ich kann einen Serializer dafür schaffen ohne Probleme, aber meine Deserializer schlägt mit der Ausnahme com.fasterxml.jackson.databind.JsonMappingException: Duplicate property 'Inners' for [simple type, class BrokenTest$Outer]
Hier werden die Unit-Tests für die Weitergabe der Serialisierung und andernfalls Deserialisierung:
import com.fasterxml.jackson.annotation.JsonCreator;
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 org.testng.annotations.Test;
import java.util.Arrays;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
public class BrokenTest
{
private static final String NAMESPACE = "http://example.com";
@JacksonXmlRootElement(localName="Outer", namespace = NAMESPACE)
public static class Outer
{
@JacksonXmlProperty(localName="Foo", namespace = NAMESPACE)
public final String foo;
@JacksonXmlProperty(localName="Inner", namespace = NAMESPACE)
@JacksonXmlElementWrapper(localName = "Inners", namespace = NAMESPACE)
public final List<Inner> inners;
@JsonCreator
public Outer(
@JacksonXmlProperty(localName="Foo", namespace = NAMESPACE) final String foo,
@JacksonXmlProperty(localName="Inners", namespace = NAMESPACE) final List<Inner> inners)
{
this.foo = foo;
this.inners = inners;
}
}
@JacksonXmlRootElement(localName="Inner", namespace = NAMESPACE)
public static class Inner
{
@JacksonXmlProperty(localName="Bar", namespace = NAMESPACE)
public final String bar;
@JacksonXmlProperty(localName="Baz", namespace = NAMESPACE)
public final String baz;
@JsonCreator
public Inner(
@JacksonXmlProperty(localName="Bar", namespace = NAMESPACE) final String bar,
@JacksonXmlProperty(localName="Baz", namespace = NAMESPACE) final String baz)
{
this.bar = bar;
this.baz = baz;
}
}
@Test
public void serializeInner() throws Exception
{
Inner inner = new Inner("inner bar", "inner baz");
ObjectMapper mapper = new XmlMapper();
String serialized = mapper.writeValueAsString(inner);
assertEquals(serialized, "<Inner xmlns=\"http://example.com\"><Bar>inner bar</Bar><Baz>inner baz</Baz></Inner>");
}
@Test
public void deserializeInner() throws Exception
{
String serialized = "<Inner xmlns=\"http://example.com\"><Bar>inner bar</Bar><Baz>inner baz</Baz></Inner>";
ObjectMapper mapper = new XmlMapper();
Inner inner = mapper.readValue(serialized, Inner.class);
assertNotNull(inner);
assertEquals("inner bar", inner.bar);
assertEquals("inner baz", inner.baz);
}
@Test
public void serializeOuter() throws Exception
{
Outer outer = new Outer("outer foo", Arrays.asList(new Inner("inner 1 bar", "inner 1 baz"), new Inner("inner 2 bar", "inner 2 baz")));
ObjectMapper mapper = new XmlMapper();
String serialized = mapper.writeValueAsString(outer);
assertEquals(serialized, "<Outer xmlns=\"http://example.com\"><Foo>outer foo</Foo><Inners><Inner><Bar>inner 1 bar</Bar><Baz>inner 1 baz</Baz></Inner><Inner><Bar>inner 2 bar</Bar><Baz>inner 2 baz</Baz></Inner></Inners></Outer>");
}
@Test
public void deserializeOuter() throws Exception
{
String serialized = "<Outer xmlns=\"http://example.com\"><Foo>outer foo</Foo><Inners><Inner><Bar>inner 1 bar</Bar><Baz>inner 1 baz</Baz></Inner><Inner><Bar>inner 2 bar</Bar><Baz>inner 2 baz</Baz></Inner></Inners></Outer>";
ObjectMapper mapper = new XmlMapper();
Outer outer = mapper.readValue(serialized, Outer.class); // fails
assertNotNull(outer);
assertEquals("outer foo", outer.foo);
assertEquals(2, outer.inners.size());
assertEquals("inner 1 bar", outer.inners.get(0).bar);
assertEquals("inner 1 baz", outer.inners.get(0).baz);
assertEquals("inner 2 bar", outer.inners.get(1).bar);
assertEquals("inner 2 baz", outer.inners.get(1).baz);
}
}
Ich kann erhalten eine andere Ausnahme (com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Inners" (class BrokenTest$Outer), not marked as ignorable (2 known properties: "Foo", "Inner"])
), wenn ich die @JacksonXmlProperty
Annotation auf Outer
Konstruktor ändern, um die localName
"Inner" anstelle von "Inneres" zu verwenden.
Gibt es eine Möglichkeit, ein Paar POJOs zu erstellen, die für diese vier Testfälle funktionieren?
bearbeitet: Dies ist mit Jackson Version 2.7.3
traurig über die offensichtlich falsche Antwort, ich war zu viel Aufmerksamkeit auf JUnit „tatsächliche Ergebnis“ zu bezahlen, die in Ihren Tests ist die „erwartete Ergebnis ". Ich werde die Antwort löschen. – nyname00
Eine seltsame Sache, die ich fand, war, dass, wenn Sie die Annotation auf "Inners" im "Outer" -Konstruktor in '@JacksonXmlProperty (localName =" XXX ", Namespace = NAMESPACE) final List Inners ändern, alle Tests bestanden. Aber du solltest das nochmal überprüfen;) –
nyname00
Du hast Recht, es funktioniert. Das ist sehr seltsam. Bitte mach das zur Antwort, damit ich es annehmen kann. –