2011-09-23 44 views
6

我正在尝试使用JAXB将HashTable<String, String>序列化为XML。我对Java很陌生(来自C#),所以我对这个任务感到困惑。如何使用JAXB将HashTable <String,String>序列化为XML?

我看到了下面的代码:

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大师能告诉我如何调用这段代码吗?提出一个更简单的实现(当然还有一个调用示例)也是非常受欢迎的。

谢谢。

回答

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是常用的替代品。
  • 约定是以小写字母开头的Java方法名称。

自定义映射

您可以使用JAXB的XmlAdapter自定义任何类的映射。下面是我的博客帖子的链接,我将演示如何做到这一点:

3

不幸的是,JAXB不能直接将MapHashMap实例直接序列化。相反,您必须从Map进行某种类型的翻译到具有密钥和值的条目列表中。尝试调查this Stack Overflow question,看看它是否可以帮助你。这个问题在Google中出现很多,而令人难过的答案是JAXB不知道如何序列化一个Map

+2

JAXB确实有映射的默认映射(请参阅http://stackoverflow.com/questions/7534500/how-to-serialize-hashtablestring-string-to-xml-using-jaxb/7534671#7534671)。您所描述的策略对于指定非默认映射是必要的。 –

1

虽然您可能熟悉C#泛化的泛型,但Java的泛型仅适用于编译时,它们在运行时会消失。这就是为什么在运行时,即使你有一个具有已建立泛型的实例(比如String for HashTable),那么这些泛型就会消失,所以你所能做的就是获取事物的类(这里是HashTable),而不是实际的泛型类型(字符串在这里)。简而言之:编译时间Hashtable<String,String>成为哈希表在运行时(或者,是完全学究HashTable<?,?>

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(); 
    } 
相关问题