一、前言
xml和json都是web存储和运输过程中的数据格式,目前我们使用更多的是json,但是在工作当中难以避免的会遇到一些老接口使用的是xml格式的入参,此时为了调用接口,我们只能将json转换成xml格式,然后进行调用,为了方便使用,我们可以使用JDK中的JAXB来进行注解式开发,这样既简单也能有效的减少我们的代码量;
接下来我们需要将这样一段json格式的数据转换成xml格式
例:
{
"name": "xiaoming",
"age": "18",
"schoolBag": {
"pencil": "晨光E-001",
"book": [{
"name": "English",
"price": "$12.3"
}, {
"name": "Math",
"price": "$12.5"
}]
},
"sex": "钢铁直男"
}
二、代码编写
我们首先编写工具类 DataUtils
@SuppressWarnings("unchecked")
public class DataUtils {
public static String objToXml(Object obj, java.lang.Class<?> load) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(load);
Marshaller marshaller = context.createMarshaller();
/** 设置格式化 编码 */
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
StringWriter writer = new StringWriter();
marshaller.marshal(obj, writer);
return String.valueOf(writer);
}
public static <T> T xmlToJson(String xml, Class<T> classType) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(classType);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (T) unmarshaller.unmarshal(new StringReader(xml));
}
}
然后新建实体类Person、SchoolBag、Book
@XmlRootElement(name = "Person")
@XmlType(propOrder = { "name", "age", "sex", "schoolBag" })
public class Person {
private String name;
private String age;
private String sex;
private SchoolBag schoolBag;
@XmlAttribute(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute(name = "age")
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@XmlAttribute(name = "sex")
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@XmlElement(name = "schoolBag")
public SchoolBag getSchoolBag() {
return schoolBag;
}
public void setSchoolBag(SchoolBag schoolBag) {
this.schoolBag = schoolBag;
}
}
public class SchoolBag {
private List<Book> book;
private String pencil;
@XmlElementWrapper(name = "book")
public List<Book> getBook() {
return book;
}
public void setBook(List<Book> book) {
this.book = book;
}
@XmlElement(name = "pencil")
public String getPencil() {
return pencil;
}
public void setPencil(String pencil) {
this.pencil = pencil;
}
}
public class Book {
private String name;
private String price;
@XmlElement(name = "name")
public String getName() {
return name;
}
public Book setName(String name) {
this.name = name;
return this;
}
@XmlElement(name = "price")
public String getPrice() {
return price;
}
public Book setPrice(String price) {
this.price = price;
return this;
}
}
三、测试
public class TestClass {
public static void main(String[] args) throws JAXBException {
Person person = new Person();
person.setName("xiaoming");
person.setAge("18");
person.setSex("钢铁直男");
ArrayList<Book> books = new ArrayList<Book>();
books.add(new Book().setName("English").setPrice("$12.3"));
books.add(new Book().setName("Math").setPrice("$12.5"));
SchoolBag schoolBag2 = new SchoolBag();
schoolBag2.setBook(books);
schoolBag2.setPencil("晨光E-001");
person.setSchoolBag(schoolBag2);
String objToXml = DataUtils.objToXml(person, Person.class);
Person xmlToJson = DataUtils.xmlToJson(objToXml, Person.class);
System.out.println(objToXml);
System.out.println(JSONObject.toJSON(xmlToJson));
}
}
执行则打印以下结果,这样一个简单的工具类就完成了!
注意
这样我们的代码就编写完毕了,首先我们需要注意的地方有以下几点
1、@XmlRootElement xml根节点注解是必须的,不可忽略,name可以不设置,默认为类名(全小写)
2、默认情况下JAXB转换出来的数据顺序是随机的,我们可以使用@XmlType对数据进行排序
3、@XmlAttribute和@XmlElement 含义是不同的,@XmlAttribute注解会将当前字段映射成对应元素的“属性”,@XmlElement则映射成一个单独的元素,从名称中我们就可以感受到之间的区别
4、JAXB注解是将被注解字段的get/set方法对应的字段映射为特定元素/属性的,所以get/set方法需要使用传统的驼峰格式,如getName、setName等,否则会出现对应字段数据没有被转换的风险
5、转换后,xml根节点会多出 standalone=“yes” 属性,不需要的可以排除