簡體   English   中英

無法使用Jackson XmlMapper反序列化包裝的List

[英]Can't deserialize a wrapped List with Jackson XmlMapper

我正在嘗試創建一對不可變的POJO來處理XML的序列化和反序列化,如下所示:

<?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>

我需要能夠序列化和反序列化包含Inner s列表和Inner本身的Outer

我可以為此創建一個序列化器沒有問題,但是我的反序列化器失敗了,例外是com.fasterxml.jackson.databind.JsonMappingException: Duplicate property 'Inners' for [simple type, class BrokenTest$Outer]

以下是傳遞序列化和失敗反序列化的單元測試:

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

我可以得到一個不同的異常( com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Inners" (class BrokenTest$Outer), not marked as ignorable (2 known properties: "Foo", "Inner"]) )如果我在Outer的構造函數上更改@JacksonXmlProperty注釋,則使用localName “Inner”而不是“Inners”。

有沒有辦法創建一對適用於這四個測試用例的POJO?

編輯 :這是使用傑克遜版本2.7.3

這是Jackson的XML處理中的一個已知錯誤

一個解決辦法是改變標注上innersOuter構造函數,因此,本地名稱是什么不是XML文件內。

以下是有效的單元測試版本:

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="XXX", 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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM