gpt4 book ai didi

java - Jackson XML Bind Element 基于属性值

转载 作者:行者123 更新时间:2023-12-02 01:33:49 26 4
gpt4 key购买 nike

我有以下XML结构:

<participants>
<participant side="AWAY">
<team id="18591" name="Orlando Apollos" />
</participant>
<participant side="HOME">
<team id="18594" name="Memphis Express" />
</participant>
</participants>

如果我使用FasterXML Jackson图书馆 JAXB注释如何将参与者字段绑定(bind)到两个不同的 Participant对象 participantHomeparticipantAway使用side AWAY的属性(property)和HOME绑定(bind)字段。

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

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

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

最佳答案

您需要编写自定义反序列化器,因为没有允许将列表项绑定(bind)到对象中给定属性的注释。如果您已经使用 Jackson 尝试实现自定义 JsonDeserializer而不是自定义XmlAdapter 。我们可以通过将内部 Participant 对象反序列化为 Map 来简化自定义反序列化器。简单的例子:

import 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 {

public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

XmlMapper xmlMapper = new XmlMapper();

Participants result = xmlMapper.readValue(xmlFile, Participants.class);
System.out.println(result);
}
}

class ParticipantsXmlAdapter extends JsonDeserializer<Participants> {

@Override
public Participants deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
List<Map<String, Object>> participants = readParticipantsMap(p, ctxt);

Participants result = new Participants();
for (Map<String, Object> participantMap : participants) {
Object side = participantMap.get("side").toString();
if ("AWAY".equals(side)) {
result.setParticipantAway(convert((Map<String, Object>) participantMap.get("team")));
} else if ("HOME".equals(side)) {
result.setParticipantHome(convert((Map<String, Object>) participantMap.get("team")));
}
}

return result;
}

private List<Map<String, Object>> readParticipantsMap(JsonParser p, DeserializationContext ctxt) throws IOException {
MapType mapType = ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class);
JsonDeserializer<Object> mapDeserializer = ctxt.findRootValueDeserializer(mapType);
List<Map<String, Object>> participants = new ArrayList<>();
p.nextToken(); // skip Start of Participants object
while (p.currentToken() == JsonToken.FIELD_NAME) {
p.nextToken(); // skip start of Participant
Object participant = mapDeserializer.deserialize(p, ctxt);
participants.add((Map<String, Object>) participant);
p.nextToken(); // skip end of Participant
}

return participants;
}

private Participant convert(Map<String, Object> map) {
Participant participant = new Participant();
participant.setId(Integer.parseInt(map.get("id").toString()));
participant.setName(map.get("name").toString());

return participant;
}
}

@JsonDeserialize(using = ParticipantsXmlAdapter.class)
class Participants {

private Participant participantHome;
private Participant participantAway;

// getters, setters, toString
}

class Participant {
private int id;
private String name;

// getters, setters, toString
}

打印:

Participants{participantHome=Participant{id=18594, name='Memphis Express'}, participantAway=Participant{id=18591, name='Orlando Apollos'}}

关于java - Jackson XML Bind Element 基于属性值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55525167/

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