You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Jackson将XML中带key属性的entry映射到POJO属性?

解决Jackson映射带key属性的XML到POJO的问题

我懂你现在的困扰——你要对接的旧系统返回的XML是<entry key="xxx">这种键值对结构,但你的POJO是平级的字段,Jackson默认没法自动把这两者对应起来对吧?别担心,我给你两种实用的解决方案,你可以根据自己的需求选:

方案一:借助中间Entry类映射后赋值

这种方式逻辑直观,容易理解和维护,适合大多数场景。我们先把所有<entry>元素解析成一个列表,再通过初始化方法把键值对映射到POJO的对应字段:

@JacksonXmlRootElement(localName = "properties")
@Data
public class Example {
    private String token;
    private String affid;
    private String domain;

    // 先将所有entry元素解析为列表,useWrapping=false表示不需要额外的包装标签
    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "entry")
    private List<Entry> entries;

    // 初始化方法,在Jackson完成对象实例化后自动执行,将entry的键值对映射到字段
    @PostConstruct
    private void mapEntriesToFields() {
        if (entries == null) return;
        for (Entry entry : entries) {
            switch (entry.getKey()) {
                case "token":
                    this.token = entry.getValue();
                    break;
                case "affid":
                    this.affid = entry.getValue();
                    break;
                case "domain":
                    this.domain = entry.getValue();
                    break;
            }
        }
        // 解析完成后清空列表,避免不必要的内存占用
        this.entries = null;
    }

    // 内部类,用来单独映射单个entry元素的属性和文本值
    @Data
    static class Entry {
        // 映射entry标签的key属性
        @JacksonXmlProperty(isAttribute = true)
        private String key;
        // 映射entry标签的文本内容
        @JacksonXmlText
        private String value;
    }
}

方案二:自定义反序列化器直接映射字段

如果你不想引入额外的内部类,可以通过自定义反序列化器,让Jackson直接匹配对应key的entry元素到POJO字段:

@JacksonXmlRootElement(localName = "properties")
@Data
public class Example {
    @JacksonXmlProperty(localName = "entry")
    @JsonDeserialize(using = EntryValueDeserializer.class)
    @JsonProperty("token")
    private String token;

    @JacksonXmlProperty(localName = "entry")
    @JsonDeserialize(using = EntryValueDeserializer.class)
    @JsonProperty("affid")
    private String affid;

    @JacksonXmlProperty(localName = "entry")
    @JsonDeserialize(using = EntryValueDeserializer.class)
    @JsonProperty("domain")
    private String domain;

    // 自定义反序列化器,提取对应key的entry文本值
    static class EntryValueDeserializer extends StdDeserializer<String> {
        public EntryValueDeserializer() {
            super(String.class);
        }

        @Override
        public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            JsonNode node = p.getCodec().readTree(p);
            String entryKey = node.get("@key").asText();
            // 获取当前要映射的POJO字段名称(通过@JsonProperty指定)
            String targetFieldKey = ctxt.getParser().getCurrentName();
            
            if (targetFieldKey.equals(entryKey)) {
                return node.asText();
            }
            return null;
        }
    }
}

测试代码

不管用哪种方案,你都可以用下面的代码测试解析是否成功:

public class XmlParsingDemo {
    public static void main(String[] args) throws IOException {
        String xmlContent = "<properties>\n" +
                "    <entry key=\"token\">rent</entry>\n" +
                "    <entry key=\"affid\">true</entry>\n" +
                "    <entry key=\"domain\">example.com</entry>\n" +
                "</properties>";

        XmlMapper xmlMapper = new XmlMapper();
        Example result = xmlMapper.readValue(xmlContent, Example.class);
        
        System.out.println("Token: " + result.getToken());
        System.out.println("Affid: " + result.getAffid());
        System.out.println("Domain: " + result.getDomain());
    }
}

小提示:方案一更适合新手或者需要后续扩展字段的场景,逻辑清晰;方案二适合追求代码简洁、不想额外定义类的场景。

内容的提问来源于stack exchange,提问作者Jesse Nelson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:21:22