环境:
Betwixt2 0.8
Java5
Apache Commons Betwixt2 真是个变态的家伙,当你用Betwixt2在java与xml之间做转换的时候,如果Bean中有集合属性,就千万要注意了。----如果你搞不好,在xml转向java的时候,集合属性就丢失了。
追其原因,是Betwixt2对带有集合的javabean转换有些约定:
1、集合属性的名字要以集合元素类的名字开头(大小写不敏感);
2、每个Bean都必须有一个不带参数的构造方法。或者bean不要写任何构造方法(这样实际上有一个默认的不带参数的构造方法)。
3、每个对于包含其他Bean集合的Bean,要有一个addXxxBean(XxxBean bean)的方法,只有这样,才能保证将xml转换为java的时候,集合属性不丢失。
由于这个原因,我差点将原来费了好大劲写好的代码推翻重做了。现在写个简单的例子放出来,希望对遇到同样问题的博友有所帮助。下面看个例子吧:
例子是这样的:一个人Person可以有多个宠物Pet,现在创建一个Person,将其转换为XML,然后做个逆转。实现代码如下:
package bt;
import java.util.ArrayList;
import java.util.List;
/**
* 人
*
* @author leizhimin 2008-10-22 10:16:06
*/
public class Person {
private String name; //姓名
private int age; //年龄
private List<Pet> petList; //拥有的宠物
//------------constructor-----------
/**
* 这个默认的构造方法不可少,否则转换出错
*/
public Person() {
petList = new ArrayList<Pet>();
}
public Person(String name, int age) {
petList = new ArrayList<Pet>();
this.name = name;
this.age = age;
}
//------------add集合成员的方法-----------
/**
* 添加集合属性元素的方法,add后的单词必须决定了xml中元素的名字
*
* @param pet
*/
public void addPet(Pet pet) {
petList.add(pet);
}
//------------getter/setter-----------
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge( int age) {
this.age = age;
}
public List<Pet> getPetList() {
return petList;
}
public void setPetList(List<Pet> petList) {
this.petList = petList;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append( "Person{" +
"name='" + name + '\'' +
", age=" + age +
", petList=\n");
for (Pet pet : petList) {
sb.append( "\t\t" + pet.toString()).append( ";\n");
}
sb.append('}');
return sb.toString();
}
}
import java.util.ArrayList;
import java.util.List;
/**
* 人
*
* @author leizhimin 2008-10-22 10:16:06
*/
public class Person {
private String name; //姓名
private int age; //年龄
private List<Pet> petList; //拥有的宠物
//------------constructor-----------
/**
* 这个默认的构造方法不可少,否则转换出错
*/
public Person() {
petList = new ArrayList<Pet>();
}
public Person(String name, int age) {
petList = new ArrayList<Pet>();
this.name = name;
this.age = age;
}
//------------add集合成员的方法-----------
/**
* 添加集合属性元素的方法,add后的单词必须决定了xml中元素的名字
*
* @param pet
*/
public void addPet(Pet pet) {
petList.add(pet);
}
//------------getter/setter-----------
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge( int age) {
this.age = age;
}
public List<Pet> getPetList() {
return petList;
}
public void setPetList(List<Pet> petList) {
this.petList = petList;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append( "Person{" +
"name='" + name + '\'' +
", age=" + age +
", petList=\n");
for (Pet pet : petList) {
sb.append( "\t\t" + pet.toString()).append( ";\n");
}
sb.append('}');
return sb.toString();
}
}
package bt;
/**
* 宠物
*
* @author leizhimin 2008-10-22 10:17:03
*/
public class Pet {
private String nikename; //昵称
private String color; //颜色
/**
* 这个默认的构造方法不可少
*/
public Pet() {
}
public Pet(String nikename, String color) {
this.nikename = nikename;
this.color = color;
}
public String getNikename() {
return nikename;
}
public void setNikename(String nikename) {
this.nikename = nikename;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String toString() {
return "Pet{" +
"nikename='" + nikename + '\'' +
", color='" + color + '\'' +
'}';
}
}
/**
* 宠物
*
* @author leizhimin 2008-10-22 10:17:03
*/
public class Pet {
private String nikename; //昵称
private String color; //颜色
/**
* 这个默认的构造方法不可少
*/
public Pet() {
}
public Pet(String nikename, String color) {
this.nikename = nikename;
this.color = color;
}
public String getNikename() {
return nikename;
}
public void setNikename(String nikename) {
this.nikename = nikename;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String toString() {
return "Pet{" +
"nikename='" + nikename + '\'' +
", color='" + color + '\'' +
'}';
}
}
package bt;
import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
import org.xml.sax.SAXException;
import java.beans.IntrospectionException;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
/**
* 超变态的Betwixt测试
*
* @author leizhimin 2008-10-22 11:28:15
*/
public class TestBetwixt {
public static void main(String[] args) throws IOException, SAXException, IntrospectionException {
String xml = java2XML();
System.out.println(xml);
Person person = xml2Java(xml);
System.out.println(person);
}
public static String java2XML() throws IOException, SAXException, IntrospectionException {
String reslutXml;
//创建一个输出流,将用来输出Java转换的XML文件
StringWriter outputWriter = new StringWriter();
//输出XML的文件头
outputWriter.write( "<?xml version='1.0' ?>\n");
//创建一个BeanWriter实例,并将BeanWriter的输出重定向到指定的输出流
BeanWriter beanWriter = new BeanWriter(outputWriter);
//配置BeanWriter对象
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives( false);
beanWriter.getBindingConfiguration().setMapIDs( false); //不自动生成ID
beanWriter.setWriteEmptyElements( true); //输出空元素
beanWriter.enablePrettyPrint(); //格式化输出
//构建要转换的对象
Person person = new Person( "唐伯虎", 24);
Pet pet1 = new Pet( "旺财", "黄色");
Pet pet2 = new Pet( "小强", "灰色");
person.getPetList().add(pet1);
person.getPetList().add(pet2);
//将对象转换为XML
beanWriter.write(person);
//获取转换后的结果
reslutXml = outputWriter.toString();
//关闭输出流
outputWriter.close();
return reslutXml;
}
public static Person xml2Java(String xml) throws IntrospectionException, IOException, SAXException {
//创建一个读取xml文件的流
StringReader xmlReader = new StringReader(xml);
//创建一个BeanReader实例,相当于转换器
BeanReader beanReader = new BeanReader();
//配置BeanReader实例
beanReader.getXMLIntrospector().getConfiguration().setAttributesForPrimitives( false);
beanReader.getBindingConfiguration().setMapIDs( false); //不自动生成ID
//注册要转换对象的类,并指定根节点名称
beanReader.registerBeanClass( "Person", Person. class);
//将XML解析Java Object
Person person = (Person) beanReader.parse(xmlReader);
return person;
}
}
import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
import org.xml.sax.SAXException;
import java.beans.IntrospectionException;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
/**
* 超变态的Betwixt测试
*
* @author leizhimin 2008-10-22 11:28:15
*/
public class TestBetwixt {
public static void main(String[] args) throws IOException, SAXException, IntrospectionException {
String xml = java2XML();
System.out.println(xml);
Person person = xml2Java(xml);
System.out.println(person);
}
public static String java2XML() throws IOException, SAXException, IntrospectionException {
String reslutXml;
//创建一个输出流,将用来输出Java转换的XML文件
StringWriter outputWriter = new StringWriter();
//输出XML的文件头
outputWriter.write( "<?xml version='1.0' ?>\n");
//创建一个BeanWriter实例,并将BeanWriter的输出重定向到指定的输出流
BeanWriter beanWriter = new BeanWriter(outputWriter);
//配置BeanWriter对象
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives( false);
beanWriter.getBindingConfiguration().setMapIDs( false); //不自动生成ID
beanWriter.setWriteEmptyElements( true); //输出空元素
beanWriter.enablePrettyPrint(); //格式化输出
//构建要转换的对象
Person person = new Person( "唐伯虎", 24);
Pet pet1 = new Pet( "旺财", "黄色");
Pet pet2 = new Pet( "小强", "灰色");
person.getPetList().add(pet1);
person.getPetList().add(pet2);
//将对象转换为XML
beanWriter.write(person);
//获取转换后的结果
reslutXml = outputWriter.toString();
//关闭输出流
outputWriter.close();
return reslutXml;
}
public static Person xml2Java(String xml) throws IntrospectionException, IOException, SAXException {
//创建一个读取xml文件的流
StringReader xmlReader = new StringReader(xml);
//创建一个BeanReader实例,相当于转换器
BeanReader beanReader = new BeanReader();
//配置BeanReader实例
beanReader.getXMLIntrospector().getConfiguration().setAttributesForPrimitives( false);
beanReader.getBindingConfiguration().setMapIDs( false); //不自动生成ID
//注册要转换对象的类,并指定根节点名称
beanReader.registerBeanClass( "Person", Person. class);
//将XML解析Java Object
Person person = (Person) beanReader.parse(xmlReader);
return person;
}
}
运行结果:
log4j:WARN No appenders could be found
for logger (org.apache.commons.betwixt.io.AbstractBeanWriter).
log4j:WARN Please initialize the log4j system properly.
<?xml version='1.0' ?>
<Person>
<age>24</age>
<name>唐伯虎</name>
<petList>
<pet>
<color>黄色</color>
<nikename>旺财</nikename>
</pet>
<pet>
<color>灰色</color>
<nikename>小强</nikename>
</pet>
</petList>
</Person>
Person{name='唐伯虎', age=24, petList=
Pet{nikename='旺财', color='黄色'};
Pet{nikename='小强', color='灰色'};
}
Process finished with exit code 0
log4j:WARN Please initialize the log4j system properly.
<?xml version='1.0' ?>
<Person>
<age>24</age>
<name>唐伯虎</name>
<petList>
<pet>
<color>黄色</color>
<nikename>旺财</nikename>
</pet>
<pet>
<color>灰色</color>
<nikename>小强</nikename>
</pet>
</petList>
</Person>
Person{name='唐伯虎', age=24, petList=
Pet{nikename='旺财', color='黄色'};
Pet{nikename='小强', color='灰色'};
}
Process finished with exit code 0
看到了吧,双向转换成功了。
但是修改下petList属性的名字,修改下getPetList、setPetList的名字,去掉默认的构造方法,使得不符合上面的约定原则,双向转换就失败了。
另外,经过Betwixt2还有一个陷阱,就是在将xml转Java过程中,如果日期数据元素为空,则导致转换失败。解决办法是,将java转xml的时候,设置忽略空元素beanWriter.setWriteEmptyElements(
false);,在将xml转java 的时候,空日期元素删除掉即可。
本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/107349,如需转载请自行联系原作者