基于属性值的杰克逊 XML 绑定元素

我有以下结构:XML


<participants>

    <participant side="AWAY">

        <team id="18591" name="Orlando Apollos" />

    </participant>

    <participant side="HOME">

        <team id="18594" name="Memphis Express" />

    </participant>

</participants>

如果我使用带有注释的库,如何将参与者字段绑定到两个不同的对象,并使用 和 的属性绑定字段。FasterXML JacksonJAXBParticipantparticipantHomeparticipantAwaysideAWAYHOME


使用以下对象显然不起作用,因为存在重复的字段:


import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name = "participants")

public class Participants {


    @XmlElement(name = "participant")

    Participant participantHome;


    @XmlElement(name = "participant")

    Participant participantAway;

}

如何使用注释或自定义实现动态绑定这些元素?JAXBJAXB


狐的传说
浏览 66回答 3
3回答

慕哥9229398

您需要编写自定义的去细节,因为没有注释允许将列表项绑定到 object 中的给定属性。如果已在使用,请尝试实现自定义&nbsp;Json 序列化程序,而不是自定义&nbsp;Xml适配器。我们可以通过将内部对象反序列化为 来简化我们的自定义去序列化器。简单示例:JacksonParticipantMapimport com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonToken;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.JsonDeserializer;import com.fasterxml.jackson.databind.annotation.JsonDeserialize;import com.fasterxml.jackson.databind.type.MapType;import com.fasterxml.jackson.dataformat.xml.XmlMapper;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Map;public class XmlMapperApp {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; File xmlFile = new File("./resource/test.xml").getAbsoluteFile();&nbsp; &nbsp; &nbsp; &nbsp; XmlMapper xmlMapper = new XmlMapper();&nbsp; &nbsp; &nbsp; &nbsp; Participants result = xmlMapper.readValue(xmlFile, Participants.class);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(result);&nbsp; &nbsp; }}class ParticipantsXmlAdapter extends JsonDeserializer<Participants> {&nbsp; &nbsp; @Override&nbsp; &nbsp; public Participants deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; List<Map<String, Object>> participants = readParticipantsMap(p, ctxt);&nbsp; &nbsp; &nbsp; &nbsp; Participants result = new Participants();&nbsp; &nbsp; &nbsp; &nbsp; for (Map<String, Object> participantMap : participants) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object side = participantMap.get("side").toString();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ("AWAY".equals(side)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.setParticipantAway(convert((Map<String, Object>) participantMap.get("team")));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if ("HOME".equals(side)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.setParticipantHome(convert((Map<String, Object>) participantMap.get("team")));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return result;&nbsp; &nbsp; }&nbsp; &nbsp; private List<Map<String, Object>> readParticipantsMap(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; MapType mapType = ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class);&nbsp; &nbsp; &nbsp; &nbsp; JsonDeserializer<Object> mapDeserializer = ctxt.findRootValueDeserializer(mapType);&nbsp; &nbsp; &nbsp; &nbsp; List<Map<String, Object>> participants = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; p.nextToken(); // skip Start of Participants object&nbsp; &nbsp; &nbsp; &nbsp; while (p.currentToken() == JsonToken.FIELD_NAME) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.nextToken(); // skip start of Participant&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object participant = mapDeserializer.deserialize(p, ctxt);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; participants.add((Map<String, Object>) participant);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.nextToken(); // skip end of Participant&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return participants;&nbsp; &nbsp; }&nbsp; &nbsp; private Participant convert(Map<String, Object> map) {&nbsp; &nbsp; &nbsp; &nbsp; Participant participant = new Participant();&nbsp; &nbsp; &nbsp; &nbsp; participant.setId(Integer.parseInt(map.get("id").toString()));&nbsp; &nbsp; &nbsp; &nbsp; participant.setName(map.get("name").toString());&nbsp; &nbsp; &nbsp; &nbsp; return participant;&nbsp; &nbsp; }}@JsonDeserialize(using = ParticipantsXmlAdapter.class)class Participants {&nbsp; &nbsp; private Participant participantHome;&nbsp; &nbsp; private Participant participantAway;&nbsp; &nbsp; // getters, setters, toString}class Participant {&nbsp; &nbsp; private int id;&nbsp; &nbsp; private String name;&nbsp; &nbsp; // getters, setters, toString}指纹:Participants{participantHome=Participant{id=18594, name='Memphis Express'}, participantAway=Participant{id=18591, name='Orlando Apollos'}}

守着一只汪

您可以使用“参与者列表”代替两个不同的参与者。用@XmlAttribute注释边(名称 = “side”,必需 = true)。然后创建两个不同的参与者对象并将其添加到列表中。

月关宝盒

这里有一些很棒的答案和替代方案,但我决定使用与列表绑定的混合,并通过实现返回正确的主队或客队的 getter 方法来返回正确的或团队,以基本上扁平化 .这将减少在整个应用程序中处理列表时的计算量。homeawayList我将以下代码添加到我的父类(每个/参与者):homeawayParticipant getHome() {&nbsp; &nbsp; return (Participant) participants.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(p -> p.getSide().equalsIgnoreCase("home"));}Participant getAway() {&nbsp; &nbsp; return (Participant) participants.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(p -> p.getSide().equalsIgnoreCase("away"));}感谢您的帮助!
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java