Java 如何在没有任何信息的情况下通过 JAXB 编组对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4146540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to marshal an object via JAXB without any information about it?
提问by yegor256
I have an object value
, which is of some type, either @XmlRootElement
-annotated, or not. I want to marshal it into XML:
我有一个 object value
,它是某种类型的,要么带@XmlRootElement
注释,要么不带注释。我想将其编组为 XML:
String value1 = "test";
assertEquals("<foo>test</foo>", toXml("foo", value1));
// ...
@XmlRootElement
class Bar {
public String bar = "test";
}
assertEquals("<foo><bar>test</bar></foo>", toXml("foo", new Bar()));
Can I do it with JAXB existing facilities, or I should create some custom analyzer?
我可以使用 JAXB 现有设施来完成,还是应该创建一些自定义分析器?
采纳答案by bdoughan
You could leverage JAXBIntrospector to do the following:
您可以利用 JAXBIntrospector 执行以下操作:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
Object value = "Hello World";
//Object value = new Bar();
JAXBContext jc = JAXBContext.newInstance(String.class, Bar.class);
JAXBIntrospector introspector = jc.createJAXBIntrospector();
Marshaller marshaller = jc.createMarshaller();
if(null == introspector.getElementName(value)) {
JAXBElement jaxbElement = new JAXBElement(new QName("ROOT"), Object.class, value);
marshaller.marshal(jaxbElement, System.out);
} else {
marshaller.marshal(value, System.out);
}
}
@XmlRootElement
public static class Bar {
}
}
With the above code when the JAXBElement is marshalled it will be qualified with an xsi:type attribute corresponding to the appropriate schema type:
使用上面的代码,当 JAXBElement 被编组时,它将使用对应于适当模式类型的 xsi:type 属性进行限定:
<ROOT
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">Hello World</ROOT>
To eliminate the qualification you can simply change the line that creates the JAXBElement to:
要消除限定,您只需将创建 JAXBElement 的行更改为:
JAXBElement jaxbElement = new JAXBElement(new QName("ROOT"), value.getClass(), value);
This will result in the following XML:
这将产生以下 XML:
<ROOT>Hello World</ROOT>
回答by skaffman
If it's not annotated with @XmlRootElement
, then JAXB does not have sufficient information to marshal it. You would need to wrap it in a JAXBElement
first.
如果它没有用 注释@XmlRootElement
,那么 JAXB 没有足够的信息来封送它。你需要JAXBElement
先把它包装起来。
Could you do some reflective lovin' to find out how to wrap the object in the appropriate JAXBElement
?
你能不能做一些反思性的爱来找出如何用合适的包装对象JAXBElement
?
回答by Daniel Szalay
Here is how to marshal value1
, which is a String
. You can pass yourObject.getClass()
to the JAXBElement
constructor, and value1
:
下面是如何编组value1
,这是一个String
. 您可以传递yourObject.getClass()
给JAXBElement
构造函数,并且value1
:
try {
JAXBContext jc = JAXBContext.newInstance();
Marshaller m = jc.createMarshaller();
String value1 = "test";
JAXBElement jx = new JAXBElement(new QName("foo"), value1.getClass(), value1);
m.marshal(jx, System.out);
} catch (JAXBException ex) {
ex.printStackTrace();
}
This works without using @XmlRootElement
. The result of the code above was:
这在不使用@XmlRootElement
. 上面代码的结果是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo>test</foo>
On the other part, this will not work with a Bar
object: javax.xml.bind.JAXBException: myPackage.Bar is not known to this context
. However, you can get the value from inside Bar
, and create the JAXBElement
with that, not the object itself.
另一方面,这不适用于Bar
对象:javax.xml.bind.JAXBException: myPackage.Bar is not known to this context
。但是,您可以从 inside 获取值Bar
,并JAXBElement
使用它创建,而不是对象本身。
回答by sajmons
I didnt find any good generic way of doing it. Here is my generic solution.
我没有找到任何好的通用方法。这是我的通用解决方案。
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.io.StringWriter;
public class XMLConverter {
/**
* Serialize object to XML string
* @param object object
* @param <T> type
* @return
*/
public static <T> String marshal(T object) {
try {
StringWriter stringWriter = new StringWriter();
JAXBContext jc = JAXBContext.newInstance(object.getClass());
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
QName qName = new QName(object.getClass().getCanonicalName(), object.getClass().getSimpleName());
JAXBElement<T> root = new JAXBElement(qName, object.getClass(), object);
m.marshal(root, stringWriter);
return stringWriter.toString();
} catch (Exception e) {
// log the exception
}
return null;
}
/**
* Deserialize XML string back to object
* @param content XML content
* @param clasz class
* @param <T> type
* @return
*/
public static <T> T unMarshal(final String content, final Class<T> clasz) {
try {
JAXBContext jc = JAXBContext.newInstance(clasz);
Unmarshaller u = jc.createUnmarshaller();
return u.unmarshal(new StreamSource(new StringReader(content)), clasz).getValue();
} catch (Exception e) {
// log the exception
}
return null;
}
}