我正在尝试使用JAXB将HashTable<String, String>
序列化为XML。我是Java新手(来自C#),所以我对此任务感到困惑。
我见过以下代码:
public static <T> String ObjectToXml(T object, Class<T> classType) throws JAXBException
{
JAXBContext jaxbContext = JAXBContext.newInstance(classType);
StringWriter writerTo = new StringWriter();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(object, writerTo); //create xml string from the input object
return writerTo.toString();
}
这是如此调用:ObjectToXml(o, ClassOfO.class)
,但HashTable<String, String>.class
是错误的(我已经知道)。
那里的Java大师能告诉我如何调用这段代码吗?提出一个更简单的实现(当然还有一个调用示例)也是最受欢迎的。
感谢。
答案 0 :(得分:6)
您需要创建一个包装类来保留Hashtable
:
package forum7534500;
import java.util.Hashtable;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Wrapper {
private Hashtable<String, String> hashtable;
public Hashtable<String, String> getHashtable() {
return hashtable;
}
public void setHashtable(Hashtable<String, String> hashtable) {
this.hashtable = hashtable;
}
}
然后您可以执行以下操作:
package forum7534500;
import java.io.StringWriter;
import java.util.Hashtable;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Wrapper.class);
Wrapper wrapper = new Wrapper();
Hashtable<String, String> hashtable = new Hashtable<String,String>();
hashtable.put("foo", "A");
hashtable.put("bar", "B");
wrapper.setHashtable(hashtable);
System.out.println(objectToXml(jc, wrapper));
}
public static String objectToXml(JAXBContext jaxbContext, Object object) throws JAXBException
{
StringWriter writerTo = new StringWriter();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(object, writerTo); //create xml string from the input object
return writerTo.toString();
}
}
这将产生以下输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wrapper>
<hashtable>
<entry>
<key>bar</key>
<value>B</value>
</entry>
<entry>
<key>foo</key>
<value>A</value>
</entry>
</hashtable>
</wrapper>
注意事项
JAXBContext
是一个线程安全的对象,应该创建一次并重用。Hashtable
已同步,如果您不需要,则使用HashMap
是常见的替代方式。自定义映射
您可以在JAXB中使用XmlAdapter
来自定义任何类的映射。以下是我博客上帖子的链接,我将演示如何做到这一点:
答案 1 :(得分:4)
不幸的是,JAXB无法直接序列化Map
或HashMap
实例。相反,您必须从Map
进行某种转换,转换为具有键和值的条目列表。尝试查看this Stack Overflow question并查看它是否可以帮助您。这个问题在Google中出现了很多,而且令人遗憾的答案是JAXB不知道如何序列化Map
。
答案 2 :(得分:3)
呸!如果您只使用 jaxb 和 hashmap 进行了Google搜索,您可以直接找到它:http://download.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html
但是,是的,我有点同意'困惑'是对任务非显而易见感觉的良好描述。
答案 3 :(得分:1)
虽然您可能熟悉C#reified generics,但Java的泛型仅用于编译时,它们会在运行时消失。这就是为什么在运行时,即使你在运行时有一个已建立泛型的实例(如HashTable的字符串),这些泛型也会消失,所以你所能做的只是获取事物的类(这里是HashTable)而不是实际的泛型types(这里是String)。简而言之:编译时Hashtable<String,String>
在运行时变为HashTable(或者,完全是迂腐的HashTable<?,?>
)
答案 4 :(得分:1)
我认为您最好的选择是创建一个反映您想要的xml架构,然后在其上运行xjc。通过这种方式,您可以控制xml看起来如何进入JaxB的内容。 http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/jaxb/xjc.html
然后,您可以将HashTable转换为生成的对象,并将其传递给静态方法的此变体。
public static <T> String ObjectToXml(T object) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
StringWriter writerTo = new StringWriter();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(object, writerTo);
return writerTo.toString();
}