【问题标题】:Identical nested XML tag with Jackson与 Jackson 相同的嵌套 XML 标记
【发布时间】:2019-03-20 21:52:16
【问题描述】:

我正在使用 Jackson 解析以下外部 XML。

<SomeRootObject>
  <Events>
    <Event>
      <EventID>248739296</EventID>
      ...
      <Event>1709</Event>
      ...

我为“事件”定义了一个 POJO。

@JacksonXmlRootElement(localName = "Event")
public class MyEvent {
    @JsonProperty("EventID")
    public String eventID;

    ...

    @JsonProperty("Event")
    public int event;

    ...

如您所见,此 POJO 中的字段之一也映射为“事件”。所以 Jackson 抱怨它不能从事件中创建一个 int:

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of int out of START_OBJECT token
at [Source: java.io.StringReader@12417468; line: 1, column: 280] (through reference chain: be.parkd.api.tnt.ram.model.RamEvents[“Event”]->java.util.ArrayList[0]->be.parkd.api.tnt.ram.model.RamEvent[“Event”]).

这个案子可以和杰克逊一起处理吗?

我想到的一个肮脏的解决方法是预处理 XML 以更改底层事件,但我更喜欢更清洁的解决方案。

【问题讨论】:

  • 您尝试将IntegerString 作为event 的类型吗?
  • 确实如此。类型没有影响。最初它是一个字符串。
  • 您可以使用 EclipseLink JAXB (MOXy) 而不是 Jacson。见:stackoverflow.com/a/17145457

标签: java xml jackson


【解决方案1】:

变体 1

以下示例读取包装在&lt;Events&gt; 元素中的&lt;Event&gt; 元素列表。 &lt;Event&gt; 本身包含另一个嵌套的 &lt;Event&gt; 元素。这对Jackson 来说似乎不是问题。

注意:我使用TypeReference&lt;List&lt;Event&gt;&gt;() {}作为序列化规则。

@Test
public void test1() throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new XmlMapper();
    List<Event> event=mapper.readValue("<Events><Event><EventID>248739296</EventID><Event>1709</Event></Event><Event><EventID>248739297</EventID><Event>1710</Event></Event></Events>", new TypeReference<List<Event>>() {
    });
    System.out.println(toString(event));
}

public String toString(Object obj) {
    try {
        StringWriter w = new StringWriter();
        new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).writeValue(w, obj);
        return w.toString();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

使用 Event.java

@JacksonXmlRootElement(localName = "Event")
public class Event {
    @JsonProperty("EventID")
    private String eventID;
    @JsonProperty("Event")
    private int event;
    public String getEventID() {
        return eventID;
    }
    public void setEventID(String eventID) {
        this.eventID = eventID;
    }
    public int getEvent() {
        return event;
    }
    public void setEvent(int event) {
        this.event = event;
    }
}

打印

[ {
  "EventID" : "248739296",
  "Event" : 1709
}, {
  "EventID" : "248739297",
  "Event" : 1710
 } ]

所以,它有效!

变体 2

@Test
public void test2() throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new XmlMapper();
    SomeRootObject object=mapper.readValue("<SomeRootObject><Events><Event><EventID>248739296</EventID><Event>1709</Event></Event><Event><EventID>248739297</EventID><Event>1710</Event></Event></Events></SomeRootObject>", SomeRootObject.class);
    System.out.println(toString(object));
}

使用 SomeRootObject.class

@JacksonXmlRootElement(localName = "SomeRootObject")
public class SomeRootObject {
    @JsonProperty("Events")
    List<Event> events;
    public SomeRootObject() {

    }
    public List<Event> getEvents() {
        return events;
    }
    public void setEvents(List<Event> events) {
        this.events = events;
    }
}

打印

{
  "Events" : [ {
    "EventID" : "248739296",
    "Event" : 1709
  }, {
    "EventID" : "248739297",
    "Event" : 1710
  } ]
}

也有效!

【讨论】:

  • 谢谢。我将测试我是否有相同的行为。我应该补充一点,我不打电话给mapper.readValue(..., Event.class)。我用更高的 XML 对象类调用映射器。
  • 经过测试,我可以确认您提供的示例确实有效。但是,使用 &lt;Events&gt;...&lt;/Events&gt; 包装 XML 输入失败。我相信 Jackson 读取了 &lt;Event&gt; 标签并推断它必须反序列化另一个 Event 对象。
  • 不确定,如果我们走在正确的轨道上。看我的编辑。我加了&lt;Events&gt;
  • 这个案例确实有效。当将new TypeReference&lt;List&lt;Event&gt;&gt;() 更改为SomeRootObject.class 时,它会失败。 SomeRootObject、Events 和 Event 有 POJO。
  • 但是我可以通过重写代码以匹配您的示例来绕过该问题。我只是想知道如果这种情况发生在更深的嵌套结构中会发生什么。
猜你喜欢
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2016-02-13
  • 2018-04-02
  • 2011-01-30
相关资源
最近更新 更多