xstream 序列化map 为 xml 问题总结

原文地址https://bbs.csdn.net/topics/380131580

今日在开发对接接口过程中,遇到一个 map 序列化为 xml 的问题,stream 提供的默认序列化方法,如一个map:

Map<String, String> testMap = new HashMap<>();
testMap.put("1","支付方式1");
testMap.put("2","支付方式2");

默认会把 map 序列化为如下结构:

<testMap>
	<entry>
		<string>1<string>
		<string>支付方式1</string>
	</entry>
	<entry>
		<string>2<string>
		<string>支付方式2</string>
	</entry>
</testMap>

显然这种序列化结果丢失了 key/value 对应关系,客户端在拿到这个结果之后,并不能正确解析结果。

解决方式

  1. 序列化为 json 返回给客户端,可行,但是因为客户端项目历史久远,改动之后,不知道会有什么样的未知问题,此方案可行但是实际中不可用;
  2. 修改注册自定义转换器,这种方法目测也可行,没有实际测试,原因同上,历史原因导致不能修改已有接口,有未知问题;
  3. 继续序列化为 xml,修改 map 序列化的实现方式,于是就找到了文章最开始的原文。同时为了尽可能不影响其他可能的 map ,我们自己实现了新的 map , 此类非常简单,继承 hashMap 即可。然后按文章中的方式对新 map 进行序列化操作,新map 与 converter 类如下所示:

自定义map

public class CorpMap<K, V> extends HashMap
{
}

序列化方法

package com.huoli.gtgj.common.bean.dg;

import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;

import java.util.Iterator;
import java.util.Map;

public class XStreamMapConverter extends AbstractCollectionConverter
{

	public XStreamMapConverter(Mapper mapper)
	{
		super(mapper);
	}

	public boolean canConvert(Class type)
	{
		// 这里只列了 CorpMap一种情况
		return type.equals(CorpMap.class);
	}

	public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context)
	{
		Map map = (Map) source;
		for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext(); )
		{
			ExtendedHierarchicalStreamWriterHelper.startNode(writer,"entry", String.class);
			Map.Entry entry = (Map.Entry) iterator.next();
			if ("java.lang.String".equals(entry.getValue().getClass().getName()))
			{
				ExtendedHierarchicalStreamWriterHelper.startNode(writer, "key", String.class);
				writer.setValue(entry.getKey().toString());
				writer.endNode();

				ExtendedHierarchicalStreamWriterHelper.startNode(writer, "value", String.class);
				writer.setValue(entry.getValue().toString());
				writer.endNode();
			}
			writer.endNode();
			//            else if("java.util.HashMap".equals(entry.getValue().getClass().getName())){
			//             ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry.getKey().toString(), Entry.class);
			//            	context.convertAnother(entry.getValue());
			//            	writer.endNode();
			//            }
		}
	}

	public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
	{
		Map map = (Map) new CorpMap<>();
		reader.moveUp();
		map.put(reader.getNodeName(), reader.getValue());
		return map;
	}
}

在需要自定义的 feild 里面做如下处理

@XStreamConverter(value = XStreamMapConverter.class)
private CorpMap<String, String> testMap;

我们最终得到结果是:

<testMap>
            <entry>
              <key>2</key>
              <value>支付方式2</value>
            </entry>
            <entry>
              <key>1</key>
              <value>支付方式1</value>
            </entry>
</testMap>

可以看到这里的顺序是被修改了的,可能的因为是 corpmap 继承了 hashmap,这个没有最终确认情况。

本例仅对 value 为 string 的情况做了处理,实际如果需要其他结果,也可以自己定义,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值