嗨,我有一个 Java 枚举,我想从 XML 来回序列化一个包含枚举值的变量以实现持久性。我的枚举是这样定义的......
public enum e_Type
{
e_Unknown,
e_Categoric,
e_Numeric
}
我的变量是这样声明的......
private e_Type type;
我希望它进入这样的 XML 标记...
<type>value</type>
在 XML 中持久化枚举值的最佳实践是什么?
嗨,我有一个 Java 枚举,我想从 XML 来回序列化一个包含枚举值的变量以实现持久性。我的枚举是这样定义的......
public enum e_Type
{
e_Unknown,
e_Categoric,
e_Numeric
}
我的变量是这样声明的......
private e_Type type;
我希望它进入这样的 XML 标记...
<type>value</type>
在 XML 中持久化枚举值的最佳实践是什么?
查看 JAXB 注释,它们是 JDK 的一部分:
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(Foo.class);
StringWriter sw = new StringWriter();
context.createMarshaller().marshal(new Foo(), sw);
System.out.println(sw);
}
@XmlRootElement
public static class Foo {
@XmlElement
private e_Type type = e_Type.e_Unknown;
}
@XmlEnum
public enum e_Type {
e_Unknown,
e_Categoric,
e_Numeric
}
您可以进一步自定义输出,例如,如果您希望外部 XML 表示不同于内部 java 枚举项名称:
@XmlEnumValue("UNKNOWN")
e_Unknown
顺便说一句:对 java 类/枚举使用大写名称是一个非常严格的约定
在收到关于 3rd 方库的回复后,我决定自己修复它,并认为我会发布我的解决方案,以防其他人需要看到它。我刚刚在枚举中添加了两个静态方法,它们负责来回发送到 XML 的内容......
public enum e_Type
{
e_Unknown,
e_Categoric,
e_Numeric;
public static e_Type type(String token)
{
return e_Type.valueOf(token);
}
public static String token(e_Type t)
{
return t.name();
}
}
这对我来说是一个好方法,因为这意味着我可以在序列化/反序列化期间使用 type() 和 token() 方法调用我的 getter 和 setter。我已将此扩展到我的所有枚举中。
我在使用 3rd 方库时遇到了两个主要问题:
尝试使用 XStream,它是一个将对象从 xml 转换为 xml 的库,并且也支持枚举。
String xml = xstream.toXML(enumObject);
另一个框架是类似于 C# XML 序列化的简单 XML 序列化。它可以处理任何对象图,包括那些包含枚举的对象图。
Serializer serializer = new Persister();
persister.write(myObject, myOutput);
枚举的序列化使用最终的 name() 方法,因此它们总是可以从 XML 中恢复。
我喜欢第一种方法。对于这样一个简单的任务,不需要包含第三方库。但是,使序列化值 == 枚举常量字面量(即“e_Unknown”、“e_Categoric”、“e_Numeric”)意味着如果开发人员重命名变量名称,它会使存储的值不可读。例如,您将 e_Unknown 保存在 XML 中,稍后将常量重命名为 UNKNOWN(为了命名)。然后您将无法检索旧值。
另一种方法是为每个枚举分配一个业务值,并将业务值存储在数据库中,这样常量名称的重命名/重构就不会破坏旧的存储值。如果您需要更多说明,我已经在博客中讨论过这个问题:3 methods to serialize Java Enums
我会第二次投票给 JAXB 2,XStream 也不错。就其价值而言,Simple 看起来很像 XStream。另请注意,注释的使用是可选的——在大多数情况下,它可以找出自动使用的字段和/或方法。而且您根本不需要使用 XML 模式(如果您愿意,可以):许多网站声称您这样做,但这是错误的(即使是简单页面也声称类似这样)。
至于外部依赖关系:如果您在 JDK 1.6 上运行,它会附带 JAXB 的捆绑实现(不仅仅是 API!)。虽然 JDK 可以避免它的臃肿(因为不是每个人都需要它,所以那些需要它的人可以只是 d/l 它 IMO),如果您确实需要它,那就太好了。并且实现非常好,非常快(仅原始 XML 解析或写入速度的 50-70%)。