Java 如何在没有任何信息的情况下通过JAXB封送对象?
我有一个对象Java 如何在没有任何信息的情况下通过JAXB封送对象?,java,xml,jaxb,Java,Xml,Jaxb,我有一个对象值,它是某种类型的,要么是@XmlRootElement-注释的,要么不是注释的。我想将其封送到XML中: String value1 = "test"; assertEquals("<foo>test</foo>", toXml("foo", value1)); // ... @XmlRootElement class Bar { public String bar = "test"; } assertEquals("<foo><bar
值
,它是某种类型的,要么是@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()));
String value1=“测试”;
资产质量(“测试”,toXml(“foo”,value1));
// ...
@XmlRootElement
分类栏{
公共字符串bar=“test”;
}
assertEquals(“test”,toXml(“foo”,newbar());
我可以使用JAXB现有的工具来完成它,还是应该创建一些自定义分析器?如果它没有使用
@XmlRootElement
注释,那么JAXB没有足够的信息来封送它。您需要首先将其包装在JAXBElement
中
您是否可以做一些反思性的工作来了解如何将对象包装到适当的
JAXBElement
?以下是如何封送value1
,它是一个字符串。您可以将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();
}
这可以在不使用@XmlRootElement
的情况下工作。上述代码的结果是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo>test</foo>
测试
另一方面,这将不适用于Bar
对象:javax.xml.bind.JAXBException:myPackage.Bar对此上下文不了解。但是,您可以从栏中获取值,并使用该值创建JAXBElement
,而不是对象本身。您可以利用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 {
}
}
使用上面的代码,当封送JAXBEElement时,它将使用对应于适当模式类型的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>
这将产生以下XML:
<ROOT>Hello World</ROOT>
你好,世界
我没有找到任何好的通用方法。这是我的通用解决方案
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;
}
}
import javax.xml.bind.*;
导入javax.xml.namespace.QName;
导入javax.xml.transform.stream.StreamSource;
导入java.io.StringReader;
导入java.io.StringWriter;
公共类XML转换器{
/**
*将对象序列化为XML字符串
*@param对象
*@param类型
*@返回
*/
公共静态字符串封送处理(T对象){
试一试{
StringWriter StringWriter=新StringWriter();
JAXBContext jc=JAXBContext.newInstance(object.getClass());
Marshaller m=jc.createMarshaller();
m、 setProperty(Marshaller.JAXB_格式的_输出,Boolean.TRUE);
QName QName=新的QName(object.getClass().getCanonicalName(),object.getClass().getSimpleName());
JAXBElement root=newjaxbelement(qName,object.getClass(),object);
m、 封送员(root,stringWriter);
返回stringWriter.toString();
}捕获(例外e){
//记录异常
}
返回null;
}
/**
*将XML字符串反序列化回对象
*@param content XML content
*@param-clasz类
*@param类型
*@返回
*/
公共静态T解组(最终字符串内容,最终类clasz){
试一试{
JAXBContext jc=JAXBContext.newInstance(clasz);
解组器u=jc.createUnmarshaller();
返回u.unmarshal(新StreamSource(新StringReader(content)),clasz.getValue();
}捕获(例外e){
//记录异常
}
返回null;
}
}
查看我的答案,了解如何使用JAXBIntrospector避免任何反射调用。工作非常完美!也许您知道如何去掉xsi:type
属性?这就是我对字符串对象得到的结果:(239)555 2390
@Vincenzo我已经更新了我的答案,详细说明了如何消除xsi:type属性。@BlaiseDoughan请查看此问题:如果使用object.getClass().getCanonicalName(),则名称空间错误
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;
}
}