如何序列化HashTable使用 JAXB 转换为 XML?

发布于 12-06 00:34 字数 822 浏览 1 评论 0原文

我正在尝试使用 JAXB 将 HashTable 序列化为 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.class 是错误的(我已经知道了)。

Java 专家可以告诉我如何调用这段代码吗?提出一个更简单的实现(当然还有一个调用示例)也是非常受欢迎的。

谢谢。

I am trying to use JAXB to serialize a HashTable<String, String> to XML. I am very new to Java (came from C#), so I am kinda perplexed by this task.

I have seen the following code:

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();
}

Which is invoked like so: ObjectToXml(o, ClassOfO.class), but HashTable<String, String>.class is wrong (that I already know).

Can Java gurus out there show me how to invoke this code? Proposing a simpler implementation (along with an invocation example, of course) is most welcome as well.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情仇皆在手 2024-12-13 00:34:23

您需要创建一个包装类来保存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< /code> 是一个线程安全对象,应该创建一次并重用。
  • Hashtable 是同步的,如果您不需要它,那么使用 HashMap 是常见的替代品。
  • 惯例是 Java 方法名称以小写字母开头。

自定义映射

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

You will need to create a wrapper class to hold onto the 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;
    }

}

Then you can do the following:

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();
    }

}

This will produce the following output:

<?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>

Things to Note

  • JAXBContext is a thread-safe object and should be created once and reused.
  • Hashtable is synchronized, if you do not need this then using HashMap is the common replacement.
  • The convention is to start Java method names with a lower case letter.

Customizing the Mapping

You can use an XmlAdapter in JAXB to customize the mapping of any class. Below is an link to a post on my blog where I demonstrate how to do just that:

无名指的心愿 2024-12-13 00:34:23

不幸的是,JAXB 无法直接序列化 MapHashMap 实例。相反,您必须进行某种从 Map 到具有键和值的条目列表的转换。尝试查看这个 Stack Overflow 问题,看看是否可以帮助你。这个问题在 Google 中经常出现,令人悲伤的答案是 JAXB 不知道如何序列化 Map

Unfortunately, JAXB is not able to directly serialize a Map or HashMap instance directly. Instead, you'll have to do some sort of translation from a Map into a list of entries that have a key and a value. Try looking into this Stack Overflow question and see if it can help you. This problem shows up a lot in Google, and the sad answer is that JAXB doesn't know how to serialize a Map.

獨角戲 2024-12-13 00:34:23

呸!如果您只用谷歌搜索jaxbhashmap,您会直接找到这个:http://download.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html

但是,是的,我有点同意“困惑”很好地描述了任务的非显而易见性的感觉。

Bah! If you had only googled on jaxb and hashmap you would have directly found this: http://download.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html

But, yes, I kind of agree that 'perplexion' is a good description of the feeling of the non-obviousness of the task.

秉烛思 2024-12-13 00:34:23

虽然您可能熟悉 C# 具体化泛型,但 Java 的泛型仅适用于编译时,它们会在运行时消失。这就是为什么在运行时,即使您有一个已建立泛型的实例(例如 HashTable 的 String),这些泛型在运行时也会消失,因此您所能做的就是获取事物的类(此处为 HashTable),而不是实际的泛型类型(此处为字符串)。简而言之:编译时 Hashtable 在运行时变成 HashTable(或者,完全迂腐的 HashTable

While you might be familiar with C# reified generics, Java's generics are for compile time only, they go away at runtime. That's why, at runtime, even if you have an instance with established generics (Such as String for HashTable) at runtime those generics go away, so all you can do is obtain the class of the thing (HashTable here) and not the actual generic types (String here). In short: compile time Hashtable<String,String> becomes HashTable at runtime (or, to be totally pedantic HashTable<?,?>)

鲜肉鲜肉永远不皱 2024-12-13 00:34:23

我认为最好的选择是创建一个反映您想要的内容的 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();
    }

I think your best bet is to create an xml schema that reflects what you want and then run xjc on it. This way you have some control over what the xml will look like w/o getting into the guts of JaxB.
http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/jaxb/xjc.html

You can then translate your HashTable to the generated object and pass it to this variation of your static method.

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();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文