如何使用JAXB将HashTable <string,string =“”>序列化为XML?</string,>

时间:2011-09-23 20:34:08

标签: java xml jaxb hashtable

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

感谢。

5 个答案:

答案 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是常见的替代方式。
  • 约定是使用小写字母启动Java方法名称。

自定义映射

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

答案 1 :(得分:4)

不幸的是,JAXB无法直接序列化MapHashMap实例。相反,您必须从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();
    }