哪个是 Java 序列化的最佳替代方案?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/239280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Which is the best alternative for Java Serialization?
提问by Alotor
I'm currently working on a project which needs to persist any kind of object (of which implementation we don't have any control) so these objects could be recovered afterwards.
我目前正在开发一个项目,该项目需要保留任何类型的对象(我们无法控制其实现),以便之后可以恢复这些对象。
We can't implement an ORM because we can't restrict the users of our library at development time.
我们无法实现 ORM,因为我们无法在开发时限制我们库的用户。
Our first alternative was to serialize it with the Java default serialization but we had a lot of trouble recovering the objects when the users started to pass different versions of the same object (attributes changed types, names, ...).
我们的第一个选择是使用 Java 默认序列化对其进行序列化,但是当用户开始传递同一对象的不同版本(属性更改类型、名称等)时,我们在恢复对象时遇到了很多麻烦。
We have tried with the XMLEncoder class (transforms an object into a XML), but we have found that there is a lack of functionality (doesn't support Enums for example).
我们曾尝试使用 XMLEncoder 类(将对象转换为 XML),但我们发现它缺乏功能(例如不支持枚举)。
Finally, we also tried JAXB but this impose our users to annotate their classes.
最后,我们还尝试了 JAXB,但这迫使我们的用户注释他们的类。
Any good alternative?
有什么好的选择吗?
采纳答案by Hyman Leow
The easiest thing for you to do is still to use serialization, IMO, but put more thought into the serialized form of the classes (which you really ought to do anyway). For instance:
您要做的最简单的事情仍然是使用序列化,IMO,但更多地考虑类的序列化形式(无论如何您确实应该这样做)。例如:
- Explicitly define the SerialUID.
- Define your own serialized form where appropriate.
- 显式定义 SerialUID。
- 在适当的地方定义您自己的序列化表单。
The serialized form is part of the class' API and careful thought should be put into its design.
序列化形式是类 API 的一部分,在设计时应仔细考虑。
I won't go into a lot of details, since pretty much everything I have said comes from Effective Java. I'll instead, refer you to it, specifically the chapters about Serialization. It warns you about all the problems you're running into, and provides proper solutions to the problem:
我不会详细介绍,因为我所说的几乎所有内容都来自 Effective Java。相反,我会向您推荐它,特别是有关序列化的章节。它会警告您遇到的所有问题,并为问题提供适当的解决方案:
http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683
http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683
With that said, if you're still considering a non-serialization approach, here are a couple:
话虽如此,如果您仍在考虑非序列化方法,这里有几个:
XML marshalling
XML 编组
As many has pointed out is an option, but I think you'll still run into the same problems with backward compatibility. However, with XML marshalling, you'll hopefully catch these right away, since some frameworks may do some checks for you during initialization.
正如许多人指出的那样,这是一种选择,但我认为您仍然会遇到与向后兼容性相同的问题。但是,通过 XML 编组,您希望能立即捕获这些内容,因为某些框架可能会在初始化期间为您做一些检查。
Conversion to/from YAML
与 YAML 之间的转换
This is an idea I have been toying with, but I really liked the YAML format (at least as a custom toString() format). But really, the only difference for you is that you'd be marshalling to YAML instead of XML. The only benefit is that that YAML is slightly more human readable than XML. The same restrictions apply.
这是我一直在玩的一个想法,但我真的很喜欢 YAML 格式(至少作为自定义 toString() 格式)。但实际上,对您来说唯一的区别是您将编组到 YAML 而不是 XML。唯一的好处是 YAML 比 XML 更具人类可读性。同样的限制适用。
回答by krosenvold
http://x-stream.github.io/is nice, please take a look at it! Very convenient
http://x-stream.github.io/不错,快来看看吧!很方便
回答by johnstok
of which implementation we don't have any control
我们无法控制哪个实现
The solution is don't do this. If you don't have control of a type's implementation you shouldn't be serialising it. End of story. Java serialisation provides serialVersionUID specifically for managing serialisation incompatibilities between different versions of a type. If you don't control the implementation you cannot be sure that IDs are being changed correctly when a developer changes a class.
解决方案是不要这样做。如果您无法控制类型的实现,则不应对其进行序列化。故事结局。Java 序列化提供了 serialVersionUID,专门用于管理类型的不同版本之间的序列化不兼容性。如果您不控制实现,则无法确保在开发人员更改类时正确更改 ID。
Take a simple example of a 'Point'. It can be represented by either a cartesian or a polar coordinate system. It would be cost prohibitive for you to build a system that could cope dynamically with these sorts of corrections - it really has to be the developer of the class who designs the serialisation.
举一个“点”的简单例子。它可以用笛卡尔坐标系或极坐标系表示。构建一个可以动态处理这些类型的更正的系统对于您来说成本过高 - 它确实必须是设计序列化的类的开发人员。
In short it's your design that's wrong - not the technology.
简而言之,是你的设计有问题——而不是技术。
回答by akuhn
回答by Kevin Day
Betwixtis a good library for serializing objects - but it's not going to be an automatic kind of thing. If the number of objects you have to serialize is relatively fixed, this may be a good option for you, but if your 'customer' is going to be throwing new classes at you all the time, it may be more effort than it's worth (Definitely easier than XMLEncoder for all the special cases, though).
Betwixt是一个很好的序列化对象库 - 但它不会是一种自动的东西。如果您必须序列化的对象数量相对固定,这对您来说可能是一个不错的选择,但是如果您的“客户”要一直向您抛出新的类,则可能会付出更多的努力而不值得(不过,对于所有特殊情况,绝对比 XMLEncoder 容易)。
Another approach is to require your customer to provide the appropriate .betwixt files for any objects they throw at you (that effectively offloads the responsibility to them).
另一种方法是要求您的客户为他们扔给您的任何对象提供适当的 .betwixt 文件(这有效地将责任转移给了他们)。
Long and short - serialization is hard- there is no completely brain dead approach to it. Java serialization is as close to a brain dead solution as I've ever seen, but as you've found, incorrect use of the version uid value can break it. Java serialization also requires use of the marker 'Serializable' interface, so if you can't control your source, you are kind of out of luck on that one.
长期和短期 - 序列化很难- 没有完全脑死亡的方法。Java 序列化是我见过的最接近脑残的解决方案,但正如您发现的,版本 uid 值的不正确使用可能会破坏它。Java 序列化还需要使用标记 'Serializable' 接口,所以如果你不能控制你的源代码,那你就有点不走运了。
If the requirement is truly as arduous as you describe, you may have to resort to some sort of BCE (Byte code modification) on the objects / aspects / whatever. This is getting way outside the realm of a small development project, and into the realm of Hibernate, Casper or an ORM....
如果需求真的像您描述的那样艰巨,您可能不得不对对象/方面/任何东西诉诸某种 BCE(字节代码修改)。这已经超出了小型开发项目的领域,进入了 Hibernate、Casper 或 ORM 的领域......
回答by anjanb
google came up with a binary protocol -- http://code.google.com/apis/protocolbuffers/is faster, has a smaller payload compared to XML -- which others have suggested as alternate.
谷歌提出了一个二进制协议——http://code.google.com/apis/protocolbuffers/与 XML 相比速度更快,有效载荷更小——其他人建议将其作为替代方案。
One of the advanteages of protocol buffers is that it can exchange info with C, C++, python and java.
协议缓冲区的优点之一是它可以与 C、C++、python 和 java 交换信息。
回答by Jim Ferrans
It's 2011, and in a commercial grade REST web services project we use the following serializers to offer clients a variety of media types:
现在是 2011 年,在商业级 REST Web 服务项目中,我们使用以下序列化程序为客户提供各种媒体类型:
- XStream(for XML but not for JSON)
- Hymanson(for JSON)
- Kryo(a fast, compact binary serialization format)
- Smile(a binary format that comes with Hymanson 1.6 and later).
- Java Object Serialization.
- XStream(用于 XML 但不适用于 JSON)
- Hyman逊(用于 JSON)
- Kryo(一种快速、紧凑的二进制序列化格式)
- Smile(Hymanson 1.6 及更高版本附带的二进制格式)。
- Java 对象序列化。
We experimented with other serializers recently:
我们最近尝试了其他序列化程序:
- SimpleXMLseems solid, runs at 2x the speed of XStream, but requires a bit too much configuration for our situation.
- YamlBeanshad a couple of bugs.
- SnakeYAMLhad a minor bug relating to dates.
Hymanson JSON, Kryo, and Hymanson Smile were all significantly faster than good old Java Object Serialization, by about 3x to 4.5x. XStream is on the slow side. But these are all solid choices at this point. We'll keep monitoring the other three.
Hymanson JSON、Kryo 和 Hymanson Smile 都明显比旧的 Java 对象序列化快了大约 3 到 4.5 倍。XStream 在缓慢的一面。但在这一点上,这些都是可靠的选择。我们将继续监视其他三个。
回答by R.Moeller
Also a very fast JDK serialization drop-in replacement: http://ruedigermoeller.github.io/fast-serialization/
也是一个非常快速的 JDK 序列化替代品:http: //rudigermoeller.github.io/fast-serialization/