使用 JABX 将 Map<String,String> 序列化成 <key>value</key>形式的字符串

前言:

JAXB(Java Architecture for XML Binding) 用于 XML 绑定的 Java 体系结构(JAXB)是允许 Java 开发人员将 Java 类映射到 XML 表示形式的软件框架。 JAXB 支持将 Java 对象编组为 XML,然后将 XML 解组为 Java 对象。
如下:

package com.c.utils.jaxb;

import com.c.utils.LoggerUtils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;

/**
 * @author zhy
 */
public class JAXbUtils {

    private JAXbUtils() {

    }


    public static <T> void save(T obj, File file) {
        try {
            JAXBContext jc = JAXBContext.newInstance(obj.getClass());
            Marshaller jaxbMarshaller = jc.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.marshal(obj, file);
            // jaxbMarshaller.marshal(obj, System.out);
        } catch (JAXBException e) {
            LoggerUtils.getLogger(JAXbUtils.class).error(e.getMessage(), e);
        }
    }


    public static <T> T load(File file, Class<? extends T> type) {
        try {
            JAXBContext jc = JAXBContext.newInstance(type);
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            return (T) unmarshaller.unmarshal(file);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }


}

JAXB 与 Map<String,String>

JAXB 默认转换 map 的结果

JABX 默认将 Map<String,String> 序列化成:

<item>
	<key>xxx<key>
	<value>xxx<value>
</item>

如下:

package com.c.utils.jaxb;

import org.junit.Assert;
import org.junit.Test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

public class JAXbUtilsTest {

    @Test
    public void saveMap() {
        Config config = new Config();
        config.map = new HashMap<>();
        String naturalSelection = "自然选择号";
        String blueSpace = "蓝色空间号";
        config.map.put(naturalSelection, "东方延绪");
        config.map.put(blueSpace, "褚岩");

        File file = new File("target/config.xml");
        JAXbUtils.save(config, file);
        Config newConfig = JAXbUtils.load(file, Config.class);
        Assert.assertNotNull(newConfig);
        Assert.assertEquals(config.map.get(naturalSelection), newConfig.map.get(naturalSelection));
        Assert.assertEquals(config.map.get(blueSpace), newConfig.map.get(blueSpace));
    }

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    static class Config {
        Map<String, String> map = new HashMap<>();
    }
}

target/config.xml 文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config>
    <map>
        <entry>
            <key>自然选择号</key>
            <value>东方延绪</value>
        </entry>
        <entry>
            <key>蓝色空间号</key>
            <value>褚岩</value>
        </entry>
    </map>
</config>
优化 JAXB 转换 MAP

理想状态,可以将其简化为以下形式( 标签名为key,内容为 value ):

<key>value</key>

则需要自定义转换器,将map转换为 w3c 的 Element 对象(其他自定义类型也可以这样实现),实现如下:

package com.c.utils.jaxb;

import com.c.utils.LoggerUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.util.HashMap;
import java.util.Map;

public class MapAdapter extends XmlAdapter<Object, Map<String, String>> {
    public static final String TEXT = "#text";

    @Override
    public Map<String, String> unmarshal(Object v) {
        Map<String, String> map = new HashMap<>();
        if (!(v instanceof Element)) {
            return map;
        }

        NodeList childNodes = ((Element) v).getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node item = childNodes.item(i);
            if (TEXT.equals(item.getNodeName())) {
                continue;
            }
            map.put(item.getNodeName(), item.getTextContent());
        }
        return map;
    }

    @Override
    public Object marshal(Map<String, String> v) {
        Document document = null;
        try {
            document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            LoggerUtils.getLogger(getClass()).error(e.getMessage(), e);
            return null;
        }

        Element rootElement = document.createElement("map");
        document.appendChild(rootElement);
        for (Map.Entry<String, String> entry : v.entrySet()) {
            Element element = document.createElement(entry.getKey());
            element.setTextContent(entry.getValue());
            rootElement.appendChild(element);
        }
        return rootElement;
    }

}


然后在需要序列化的 map 字段上加上 @XmlJavaTypeAdapter(MapAdapter.class) 注解。

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    static class Config {
        @XmlElement(name = "properties")
        @XmlJavaTypeAdapter(MapAdapter.class)
        Map<String, String> map = new HashMap<>();
    }

修改后 target/config.xml 文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config>
    <properties>
        <自然选择号>东方延绪</自然选择号>
        <蓝色空间号>褚岩</蓝色空间号>
    </properties>
</config>

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非理性地界生物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值