Java 如何在不创建包装器类的情况下封送Jaxb元素列表?
除了组成一个writer并将每个元素附加到字符串之外。有没有一种方法可以让JAXB marshaller整理一个对象列表,让我只给它一个顶级元素的名称 我觉得我已经接近了Java 如何在不创建包装器类的情况下封送Jaxb元素列表?,java,xml,jaxb,Java,Xml,Jaxb,除了组成一个writer并将每个元素附加到字符串之外。有没有一种方法可以让JAXB marshaller整理一个对象列表,让我只给它一个顶级元素的名称 我觉得我已经接近了 //http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html public <T> String jaxb(Collection<T> o, Class<T> clazz, String plural){ t
//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
public <T> String jaxb(Collection<T> o, Class<T> clazz, String plural){
try {
ArrayList<T> al = new ArrayList<T>(o.size());
al.addAll(o);
JAXBContext jc = JAXBContext.newInstance(ArrayList.class);
JAXBElement<ArrayList> amenity = new JAXBElement(new QName(plural), ArrayList.class, al);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(amenity, writer);
return writer.toString();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
公共字符串jaxb(集合o,类clazz,字符串复数){
试一试{
ArrayList al=新的ArrayList(o.size());
艾德尔(o);
JAXBContext jc=JAXBContext.newInstance(ArrayList.class);
JAXBElement礼仪=新的JAXBElement(新的QName(复数),ArrayList.class,al);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
马歇尔(礼仪,作家);
返回writer.toString();
}捕获(JAXBEException e){
抛出新的运行时异常(e);
}
}
但结果仍然是一张空名单
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pluralName/>
有没有一种方法不需要手动将xml字符串粘贴在一起就可以做到这一点
更新
在Michael Glavassevich的帮助下,我已经能够做到这一点,但需要注意的是,单个元素是
s
//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
@SuppressWarnings({“unchecked”,“rawtypes”})
公共字符串jaxb(集合元素,类elementClass,字符串复数){
试一试{
T[]数组=(T[])array.newInstance(elementClass,elements.size());
元素。toArray(数组);
JAXBContext jc=JAXBContext.newInstance(array.getClass());
JAXBElement topElement=new-JAXBElement(新的QName(复数),array.getClass(),array);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
marshaller.Marshall(topElement,writer);
返回writer.toString();
}捕获(JAXBEException e){
抛出新的运行时异常(e);
}
}
结果就是
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Basketballs>
<item>basketball one</item>
<item>basketball two</item>
</Basketballs>
篮球一号
篮球二号
请尝试以下操作:
首先,创建一个列表类:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class AmenityList {
@XmlElement(name = "amenity")
List<Amenity> amenities = new ArrayList<Amenity>();
public AmenityList() {}
public void setList(List<Amenity> amenities) {
this.amenities = amenities;
}
}
在列表中设置所需的便利设施(可能以较少冗余的方式:)-并将其分配给便利设施列表:
AmenityList amenityList = new AmenityList();
List <Amenity> amenities = new ArrayList<Amenity>();
amenities.add(new Amenity("a_one", "today"));
amenities.add(new Amenity("a_two", "tomorrow"));
amenity.setList(amenities);
获得,即:
<amenityList>
<amenity>
<amenityName>a_one</amenityName>
<amenityDate>today</amenityDate>
</amenity>
<amenity>
<amenityName>a_two</amenityName>
<amenityDate>tomorrow</amenityDate>
</amenity>
</amenityList>
一个
今天
a_2
明天
如果不想创建包装类,可以将集合转换为数组,将该数组放入JAXBElement
中,然后封送它
例如:
public class JAXBArrayWriter {
public static class Item {
@XmlValue
protected String value;
public Item() {}
public Item(String value) {
this.value = value;
}
}
public static void main (String [] args) throws Exception {
List<Item> items = new ArrayList<Item>();
items.add(new Item("one"));
items.add(new Item("two"));
JAXBContext jc = JAXBContext.newInstance(Item[].class);
JAXBElement<Item[]> root = new JAXBElement<Item[]>(new QName("items"),
Item[].class, items.toArray(new Item[items.size()]));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(root, writer);
System.out.println(writer.toString());
}
}
公共类JAXBarryWriter{
公共静态类项{
@XmlValue
保护字符串值;
公共项(){}
公共项(字符串值){
这个值=值;
}
}
公共静态void main(字符串[]args)引发异常{
列表项=新建ArrayList();
项目。添加(新项目(“一”);
增加(新项目(“两”);
JAXBContext jc=JAXBContext.newInstance(Item[].class);
JAXBElement root=新的JAXBElement(新的QName(“项”),
Item[].class,items.toArray(新项[items.size()]);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
marshaller.marshall(root,writer);
System.out.println(writer.toString());
}
}
生成以下文档:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
<item>one</item>
<item>two</item>
</items>
一
二
使用数组的公认解决方案可以工作,但会导致每个内部元素被命名:公共类包装器{
私有列表项=新的ArrayList();
@xmlanyement(lax=true)
公共列表getItems(){
退货项目;
}
}
//JAXBContext是线程安全的,因此在构造函数或
//塞特或任何地方:
...
JAXBContext jc=JAXBContext.newInstance(Wrapper.class,clazz);
...
公共字符串封送处理(列出事物,类clazz){
//配置JAXB和marshaller
Marshaller m=jc.createMarshaller();
m、 setProperty(Marshaller.JAXB_格式化的_输出,true);
//基于通用对象列表创建包装器
包装器=新包装器(物品);
JAXBElement-wrapperJAXBElement=new-JAXBElement(新的QName(clazz.getSimpleName().toLowerCase()+“s”)、Wrapper.class、Wrapper);
StringWriter结果=新建StringWriter();
//元帅!
m、 封送员(包装、结果);
返回result.toString();
}
它不需要将列表转换为数组,但需要一个通用类。试试这个
POJO类:
@XmlRootElement(name = "classNameTAG")
@XmlAccessorType(XmlAccessType.FIELD)
public class ClassName {
@XmlElementWrapper(name="listTAG")
@XmlElement(name="itemTAG")
private List<ClassItem> items;
}
Xml结果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<classNameTAG>
<listTAG>
<itemTAG>data</itemTAG>
<itemTAG>data</itemTAG>
</listTAG>
</classNameTAG>
数据
数据
这对我来说很有用。我不知道对象列表会是便利设施,这就是为什么我尝试在没有包装器类的情况下完成它。这是正确的方向,但我在一个部分上遇到了一些问题。如果我不知道该类的类型,您知道如何将该类传递到
JAXBContext.newInstance()
?显然,我不能JAXBContext.newInstance(t[].class)
实际上,不管我怎么想。不过我还有一个问题。如果我在您的演示中将项目类名称更改为类似Basketball的名称。单个元素仍然显示为
。您知道如何更改吗?似乎与多维数组的映射规则有关,相当于具有
的模式类型。至少在规范级别上,这是不可配置的。要生成JSON而不是XML,上述方法需要做哪些更改
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
<item>one</item>
<item>two</item>
</items>
public class Wrapper<T> {
private List<T> items = new ArrayList<T>();
@XmlAnyElement(lax=true)
public List<T> getItems() {
return items;
}
//JAXBContext is thread safe and so create it in constructor or
//setter or wherever:
...
JAXBContext jc = JAXBContext.newInstance(Wrapper.class, clazz);
...
public String marshal(List<T> things, Class clazz) {
//configure JAXB and marshaller
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//Create wrapper based on generic list of objects
Wrapper<T> wrapper = new Wrapper<T>(things);
JAXBElement<Wrapper> wrapperJAXBElement = new JAXBElement<Wrapper>(new QName(clazz.getSimpleName().toLowerCase()+"s"), Wrapper.class, wrapper);
StringWriter result = new StringWriter();
//marshal!
m.marshal(wrapperJAXBElement, result);
return result.toString();
}
@XmlRootElement(name = "classNameTAG")
@XmlAccessorType(XmlAccessType.FIELD)
public class ClassName {
@XmlElementWrapper(name="listTAG")
@XmlElement(name="itemTAG")
private List<ClassItem> items;
}
public static void pojo2xml(ClassName classData, File outputFile) throws Exception {
JAXBContext context;
BufferedWriter writer = null;
writer = new BufferedWriter(new FileWriter(outputFile));
context = JAXBContext.newInstance(ClassName.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(classData, writer);
writer.close();
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<classNameTAG>
<listTAG>
<itemTAG>data</itemTAG>
<itemTAG>data</itemTAG>
</listTAG>
</classNameTAG>