Java 如何序列化哈希表<;字符串,字符串>;使用JAXB转换XML?

Java 如何序列化哈希表<;字符串,字符串>;使用JAXB转换XML?,java,xml,jaxb,hashtable,Java,Xml,Jaxb,Hashtable,我试图使用JAXB将哈希表序列化为XML。我对Java非常陌生(来自C),所以我对这个任务有点困惑 我看到了以下代码: public static <T> String ObjectToXml(T object, Class<T> classType) throws JAXBException { JAXBContext jaxbContext = JAXBContext.newInstance(classType); StringWriter writerTo

我试图使用JAXB将
哈希表
序列化为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(T对象,类类型)抛出JAXBEException
{
JAXBContext JAXBContext=JAXBContext.newInstance(类类型);
StringWriter writerTo=新建StringWriter();
Marshaller=jaxbContext.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
marshaller.marshall(object,writerTo);//从输入对象创建xml字符串
将writerTo.toString()返回;
}
这样调用:
ObjectToXml(o,ClassOfO.class)
,但是
HashTable.class
是错误的(我已经知道)

Java大师能告诉我如何调用这段代码吗?提出一个更简单的实现(当然还有一个调用示例)也是最受欢迎的


谢谢。

不幸的是,JAXB无法直接序列化
Map
HashMap
实例。相反,您必须将
映射
转换为具有键和值的条目列表。试着调查一下,看看它是否能帮助你。这个问题在Google中经常出现,令人悲哀的答案是JAXB不知道如何序列化
映射

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

您需要创建一个包装类来保存
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;
    }

}
用于UM7534500的包;
导入java.util.Hashtable;
导入javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
公共类包装器{
私有哈希表;
公共哈希表getHashtable(){
返回哈希表;
}
公共void setHashtable(Hashtable 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();
    }

}
用于UM7534500的包;
导入java.io.StringWriter;
导入java.util.Hashtable;
导入javax.xml.bind.JAXBContext;
导入javax.xml.bind.JAXBException;
导入javax.xml.bind.Marshaller;
公开课演示{
公共静态void main(字符串[]args)引发异常{
JAXBContext jc=JAXBContext.newInstance(Wrapper.class);
包装器=新包装器();
Hashtable Hashtable=新的Hashtable();
hashtable.put(“foo”,“A”);
hashtable.put(“bar”、“B”);
setHashtable(hashtable);
System.out.println(objectToXml(jc,wrapper));
}
公共静态字符串objectToXml(JAXBContext JAXBContext,Object Object)抛出JAXBEException
{
StringWriter writerTo=新建StringWriter();
Marshaller=jaxbContext.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
marshaller.marshall(object,writerTo);//从输入对象创建xml字符串
将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>

酒吧
B
福
A.
需要注意的事项

  • JAXBContext
    是一个线程安全的对象,应该创建一次并重用
  • Hashtable
    是同步的,如果您不需要它,那么使用
    HashMap
    是常见的替代方法
  • 约定是以小写字母开头Java方法名称
自定义映射

您可以在JAXB中使用
XmlAdapter
,自定义任何类的映射。下面是我博客上一篇文章的链接,我在这里演示了如何做到这一点:


我认为最好的办法是创建一个反映所需内容的xml模式,然后在其上运行xjc。通过这种方式,您可以在某种程度上控制xml的外观,即进入JaxB的内部。

然后可以将哈希表转换为生成的对象,并将其传递给静态方法的这个变体

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();
    }
public静态字符串ObjectToXml(T object)抛出jaxbeexception{
JAXBContext JAXBContext=JAXBContext.newInstance(object.getClass());
StringWriter writerTo=新建StringWriter();
Marshaller=jaxbContext.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
marshaller.marshall(object,writerTo);
将writerTo.toString()返回;
}

呸!如果您只在谷歌上搜索jaxb和hashmap,您会直接发现:


但是,是的,我同意“困惑”是对任务不明显感觉的一种很好的描述。

JAXB确实有一个默认的映射(请参阅)。您描述的策略对于指定默认映射以外的映射是必需的。一个更简单的答案,也是比适配器IMHO更易于维护的,就是在文件中存储一个简单的类型,例如成对数组,然后在读取文件时通过循环数组元素来构造映射。