【发布时间】:2008-09-18 19:30:26
【问题描述】:
假设我想在 XML 中存储很多小的配置对象,我不太关心格式。 JDK 中内置的 XMLDecoder 类可以工作,据我所知,XStream 的工作方式类似。
每个库的优势是什么?
【问题讨论】:
标签: java xml serialization xstream
假设我想在 XML 中存储很多小的配置对象,我不太关心格式。 JDK 中内置的 XMLDecoder 类可以工作,据我所知,XStream 的工作方式类似。
每个库的优势是什么?
【问题讨论】:
标签: java xml serialization xstream
我真的很喜欢XStream 图书馆。它在输出相当简单的 xml 方面做得非常好 作为提供的 Java 对象的结果。它非常适合复制 从 xml 返回的对象也是如此。而且,我们的第 3 方库之一 反正已经依赖了。
我们选择使用它是因为我们想要 我们的 xml 是人类可读的。使用 别名功能很重要 更好。
您可以扩展库,如果您 想要一个对象的某些部分 以更好的方式反序列化。我们 在一种情况下这样做了,所以文件 会有一组度数, 纬度的分和秒 和经度,而不是两个 双打。
两分钟的教程总结了基本用法,但在 有兴趣将信息保存在一个地方,我会尝试总结一下 在这里,稍微短一点。
// define your classes
public class Person {
private String firstname;
private PhoneNumber phone;
// ... constructors and methods
}
public class PhoneNumber {
private int code;
private String number;
// ... constructors and methods
}
然后使用库写出xml。
// initial the libray
XStream xstream = new XStream();
xstream.alias("person", Person.class); // elementName, Class
xstream.alias("phone", PhoneNumber.class);
// make your objects
Person joe = new Person("Joe");
joe.setPhone(new PhoneNumber(123, "1234-456"));
// convert xml
String xml = xstream.toXML(joe);
您的输出将如下所示:
<person>
<firstname>Joe</firstname>
<phone>
<code>123</code>
<number>1234-456</number>
</phone>
</person>
返回:
Person newJoe = (Person)xstream.fromXML(xml);
XMLEncoder 是为 Java bean 序列化提供的。上次用的时候, 该文件看起来相当讨厌。如果真的不在乎文件的样子,它可以 为您工作,您可以避免第三方依赖,这也很好。我希望使用 XMLEncoder 使序列化更漂亮的可能性也会更大。
如果您不给名称起别名,XStream 会输出完整的类名。如果上面的 Person 类有
package example; xml 将包含“example.Person”,而不仅仅是“person”。
【讨论】:
另一个建议:考虑使用 JAXB (http://jaxb.dev.java.net)。如果您使用的是 JDK 1.6,它是捆绑的,请查看“javax.xml.bind”了解详细信息,因此无需额外的外部 jar。
JAXB 相当快。我也喜欢 XStream,但它有点慢。此外,XMLEncoder 有点像玩具(与其他选项相比)......但如果它有效,那么使用它并没有什么坏处。
另外:JAXB 的一个好处是您还可以使用它绑定部分文档(子树);无需为整个文件创建对象。为此,您需要使用 Stax (XMLStreamReader) 指向子树的根元素,然后绑定。无需使用 SAX,即使对于大多数大文件,只要可以逐块处理即可。
【讨论】:
如果您计划将所有这些配置对象存储在一个文件中,并且该文件将非常大,那么您上面概述的两个选项都可能会占用大量内存,因为它们都需要读取整个文件进入内存进行反序列化。
如果内存使用是一个问题(包含 XML 的文件会非常大),我推荐SAX。
如果内存使用不是问题(包含 XML 的文件不会很大),我会使用默认 JRE 中包含的任何内容(在本例中为 XMLDecoder)来删除第 3 方依赖项。
【讨论】:
我也更喜欢XStream,因为它非常易于使用和扩展。如果您使用默认设置,您可以快速开始。如果您需要自定义行为,它具有非常干净的 API 和大量扩展点,因此您可以非常精细地控制要调整的内容,而不会干扰编组过程的其他部分。
由于 XStream 创建的 XML 看起来不错,手动编辑也很简单。如果输出不能满足您的需求,并且可用Converters 的长列表不包含您需要的,那么编写您自己的相当简单。
一大优点是他们的homepage 上的良好文档。
【讨论】:
我总是觉得 XStream 很诱人,因为它很容易上手。但是,我总是最终更换它。它确实有很多 bug,它的集合处理可能需要大量工作。
因此,我通常会切换到 JAXB。它比 XStream 更健壮,几乎没有错误,而且更灵活。
【讨论】:
添加到@jay 的答案示例:
代码:
PortfolioAlternateIdentifier identifier = new PortfolioAlternateIdentifier();
identifier.setEffectiveDate(new Date());
identifier.setSchemeCode("AAA");
identifier.setIdentifier("123456");
使用 XStream 的输出:
<PortfolioAlternateIdentifier>
<effectiveDate>2014-05-02 20:14:15.961 IST</effectiveDate>
<schemeCode>AAA</schemeCode>
<identifier>123456</identifier>
</PortfolioAlternateIdentifier>
使用 XMLEncoder 的输出:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0_38" class="java.beans.XMLDecoder">
<object class="PortfolioAlternateIdentifier">
<void property="effectiveDate">
<object class="java.util.Date">
<long>1399041855961</long>
</object>
</void>
<void property="identifier">
<string>123456</string>
</void>
<void property="schemeCode">
<string>AAA</string>
</void>
</object>
</java>
【讨论】:
Java 还有一个新的实用程序类,旨在存储配置中典型的键值对集。它是老式的,但非常简单和方便。这是通过 java.util.Properties 类完成的,这是一个带有序列化选项的 Map 对象。除非您存储整个对象,否则这可能就是您所需要的。
【讨论】:
如果你要持久化大量对象或者你的系统需要多线程,你应该避免像瘟疫那样使用 XMLEncoder/XMLDecoder。有关可怕的详细信息,请参阅http://matthew.mceachen.us/blog/do-not-want-xmlencoder-129.html。
如果您必须使用 XML,XStream 非常棒。但是问问自己是否真的需要使用 XML。这是一个序列化基准项目,它可能会帮助您找到更好的解决方案:
http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking
【讨论】: