【问题标题】:How do I serialize a complex Map object?如何序列化复杂的 Map 对象?
【发布时间】:2018-11-05 20:57:10
【问题描述】:

我必须在只能传输字符串的系统中传递一个对象。序列化非常适合我的需要,但我无法让这个指标对象正确序列化。

Java 创建对象:

Map<String, HashMap<String, String>> metrics = new HashMap<String, HashMap<String, String>>();
String serializedObject = "";
            try {
                 ByteArrayOutputStream bo = new ByteArrayOutputStream();
                 ObjectOutputStream so = new ObjectOutputStream(bo);
                 so.writeObject(metrics);
                 so.close();
                 serializedObject = bo.toString();
            } catch (Exception e) {
                 System.out.println(e);
            }

…将 serializedObject 作为字符串传递…

Java 将对象反消毒为度量对象。

Map<String, HashMap<String, String>> metrics = new HashMap<String, HashMap<String, String>>();

try {
                 byte b[] = serializedObject.getBytes(); 
                 ByteArrayInputStream bi = new ByteArrayInputStream(b);
                 ObjectInputStream si = new ObjectInputStream(bi);
                 metrics = (Map<String, HashMap<String, String>>) si.readObject();
                 si.close();
            } catch (Exception e) {
                 System.out.println(e);
            }

我没有收到错误,但打印出序列化对象的字节表明它太小而不能成为我正在序列化的数据。

【问题讨论】:

  • 不打印字节,为什么不在序列化之前和反序列化之后打印 Map,而不是猜测它是否太小?或者更好的是,测试该机器人是否相等。另外,您是否阅读过 ByteArrayOutputStream.toString() 的 javadoc?对任意字节使用该方法似乎是个好主意?

标签: java serialization hashmap


【解决方案1】:

这是因为您使用toString()getBytes()byte[] 映射到String。那是行不通的,你的序列化数据会被破坏,因为这个 String 方法不是为处理随机字节序列而设计的。

如果您需要传输byte[],请使用InputStream.read()OutputStream.write() 将其写入并读取。例如,只需将byte[]new ByteArrayInputStream(bo.toByteArray()) 一起传递就可以了:

Map<String, Map<String, String>> metrics = new HashMap<>();
metrics.put("test", new HashMap<>());

ByteArrayOutputStream bo = new ByteArrayOutputStream();

ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(metrics);
so.close();

ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream si = new ObjectInputStream(bi);
Map<String, Map<String, String>> result = (Map<String, Map<String, String>>) si.readObject();
si.close();

System.out.println(result.equals(metrics)); // true

【讨论】:

  • bo.toByteArray() 有没有办法将它作为字符串发送?我正在使用 Hadoop Map/Reduce,我只能在我的环境中发送一个字符串。
  • @JoshuaHedges 如果必须传递字符串,可以将其编码为 Base64 字符串。
  • @JoshuaHedges - Hadoop 确实有一个 BytesWritable 类,您可以将其用于任意字节 [] 数据 - hadoop.apache.org/docs/stable/api/index.html?org/apache/hadoop/…
  • 我通过 conf.set("property-name", serializedMap) 将这个经过消毒的对象作为属性传递给 Map reduce 作业。我从网络服务中获取数据。我在 Java 7 中,所以我必须使用 DataTypeConverter 进行“Base64”转换。我看到了长加密字符串。我想我已经接近了。感谢您的帮助。
  • 您是否考虑过将您的 Map 转换为 JsonString?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多