一、前言
json 与xml格式相互和常见,对于不用的系统,有的系统可能是json格式,有的可能是xml格式,对于一些中间平台,从第一个平台获取到的数据可能是json格式,等到自己处理完需要给另一个平台校验的却是xml格式,同时在xml中字段全大写或者首字母大写,或者某个词特有。对日期格式的要求也可能不同。自己遇到了,总结下来;
二、环境
开发工具: IDEA
json : fastJson (阿里的,这几种jsno里性能优秀的一个,网上有比对信息)
xml转换工具: thoughtworks.xstream (转换方便,效率也还Ok)
三、 Maven 依赖
1) fastjson 依赖
<!-- 阿里巴巴JSON处理器-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
- xstream依赖
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
四、Model 类(报文)
每个公司可能有不同的要求,比如对于一个实体,可能都要求用Entity结尾,我们是用Model结尾,如果是这样,如果不做处理,直接转换是会出问题的。所以才有了这篇文章。
1) RequestModel
package com.zlc.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @ClassName : RequestModel
* @描述 : request(报文)
* @Author : 追到乌云的尽头找太阳
* @Date : 2019/9/9 9:59
**/
public class RequestModel {
@XStreamAlias("Header")
private RequestHeader header;
// 请求头
@XStreamAlias("Body")
private RequestBody body;
// 请求体
// 省略set、get以及toString 方法
}
2)RequestHeadel
package com.zlc.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.Date;
/**
* @ClassName : RequestHeader
* @描述 : 请求头
* @Author : zlc
* @Date : 2019/9/9 9:59
**/
public class RequestHeader {
@XStreamAlias("Method")
private String requestMethod;
@XStreamAlias("TimeStamp")
private Date sendTime;
@XStreamAlias("WhereFrom")
private String whereFrom;
// 省略set、get以及toString方法
}
3) RequestBody
package com.zlc.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @ClassName : RequestBody
* @描述 : 请求体
* @Author : 追到乌云的尽头找太阳
* @Date : 2019/9/9 9:59
**/
public class RequestBody {
@XStreamAlias("Teacher")
private TeacherModel teacherModel;
@XStreamAlias("Grade")
private GradeModel gradeModel;
// 省略set、get以及toString方法
}
4) TeacherModel
package com.zlc.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @ClassName : TeacherModel
* @描述 : 教师
* @Author : 追到乌云的尽头找太阳
* @Date : 2019/9/9 10:22
**/
public class TeacherModel {
@XStreamAlias("ID")
private Integer id;
@XStreamAlias("Name")
private String name;
}
5)GradeModel
package com.zlc.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import java.util.List;
/**
* @ClassName : GradeModel
* @描述 : 年级
* @Author : 追到乌云的尽头找太阳
* @Date : 2019/9/9 10:16
**/
public class GradeModel {
private Integer id;
@XStreamAlias("Name")
private String name;
@XStreamImplicit(itemFieldName="Students")
private List<StudentModel> students;
}
6)StudentModel
package com.zlc.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.zlc.xmltool.XmlDateConverter;
import java.util.Date;
/**
* @ClassName : StudentModel
* @描述 : 学生
* @Author : 追到乌云的尽头找太阳
* @Date : 2019/9/9 10:16
**/
public class StudentModel {
@XStreamAlias("ID")
private Integer id;
@XStreamAlias("FirstName")
private String firstName;
@XStreamAlias("LastName")
private String lastName;
@XStreamAlias("Birthday")
@XStreamConverter(value = XmlDateConverter.class)
private Date birthday;
@XStreamAlias("City")
private String city;
@XStreamAlias("Age")
private int age;
}
- XmlDateConverter 日期转换器
package com.zlc.xmltool;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* ClassName : XmlDateConverter
* 描述 : Xml日期转换器,设定时间格式 XStream 支持时间格式为:yyyy-MM-dd HH:mm:ss. 'UTC'(根据需要配置时间格式)
* Use: 可以通过注解的形式配置在 日期格式的类属性上,应用于序列化为XML时
* Example : @XStreamConverter(value = XmlDateConverter.class)
private Date cvalidate;
* Data : 2019/8/8 10:03
* @author zlc
**/
public class XmlDateConverter extends AbstractSingleValueConverter {
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public boolean canConvert(Class type) {
return type.equals(Date.class);
}
@Override
public Object fromString(String str) {
try {
return dateFormat.parseObject(str);
} catch (ParseException e) {
e.printStackTrace();
}
throw new ConversionException("Cannot parse date " + str);
}
@Override
public String toString(Object obj) {
return dateFormat.format((Date) obj);
}
}
五、说明
这种方法就是通过注解的方法将实体转换为xml时为其取个别名,这样就可以在 不影响java的驼峰的规则下,对实体进行“定制”。日期转换器是为了对日期的格式进行设置,可以看日期转化器上面的注解,进行过测试了;对于list集合属性,可以通过使用注解@XStreamImplicit(itemFieldName=“XXX”) 进行设置;
1)注解 @XStreamAlias(“ProdCount”) 可以为普通的字段进行别名设置
2)注解 @XStreamImplicit(itemFieldName=“Product”) 可以对list集合进行别名设置
3)注解 @XStreamConverter(value = XmlDateConverter.class) 日期转化器
4)注解 @XStreamOmitField 忽略某个字段
六、测试
对于直接将json字符串转换为对象,下篇介绍吧,挺简单的;测试就是用对象直接去设置,最后打印获取到的xml格式报文;
1)测试main (ps: 因为把这些直接弄成json格式的String有点长,同时这些都是我自己新写的测试类,所以没有贴公司的真正报文,保密)
package com.zlc.main;
import com.thoughtworks.xstream.XStream;
import com.zlc.model.*;
import com.zlc.vo.Student;
import com.zlc.xmltool.XmlTransformationTool;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @ClassName : JsonToXmlMain
* @描述 : 测试main
* @Author : 追到乌云的尽头找太阳
* @Date : 2019/9/9 19:36
**/
public class JsonToXmlMain {
public static void main(String[] args) {
RequestModel requestModel = new RequestModel();
// 请求头
RequestHeader header = new RequestHeader();
header.setRequestMethod("POST");
header.setWhereFrom("127.0.0.250");
header.setSendTime(new Date());
requestModel.setHeader(header);
// 请求体
RequestBody body = new RequestBody();
// 教师
TeacherModel teacherModel = new TeacherModel();
teacherModel.setId(1);
teacherModel.setName("乌云");
body.setTeacherModel(teacherModel);
// 年级
GradeModel gradeModel = new GradeModel();
gradeModel.setId(2);
gradeModel.setName("社会一年级");
// 学生集合
List<StudentModel> students = new ArrayList<>();
StudentModel studentModel1 = new StudentModel();
studentModel1.setId(123);
studentModel1.setAge(24);
Date date = new Date();
studentModel1.setBirthday(new Date());
studentModel1.setCity("北京");
studentModel1.setFirstName("赵");
studentModel1.setLastName("大大");
students.add(studentModel1);
StudentModel studentModel2 = new StudentModel();
studentModel2.setId(213);
studentModel2.setAge(24);
studentModel2.setBirthday(new Date());
studentModel2.setCity("上海");
studentModel2.setFirstName("钱");
studentModel2.setLastName("大大");
students.add(studentModel2);
StudentModel studentModel3 = new StudentModel();
studentModel3.setId(321);
studentModel3.setAge(24);
studentModel3.setBirthday(new Date());
studentModel3.setCity("山西");
studentModel3.setFirstName("薛");
studentModel3.setLastName("小小");
students.add(studentModel3);
gradeModel.setStudents(students);
body.setGradeModel(gradeModel);
requestModel.setBody(body);
XStream xStream = new XStream();
xStream.alias("Package", RequestModel.class);
xStream.processAnnotations(RequestModel.class);
String message = xStream.toXML(requestModel);
System.out.println(message);
}
}
2)测试结果 xml报文
"D:\Program Files\Java\jdk1.8.0_31\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA
<Request>
<Header>
<Method>POST</Method>
<TimeStamp>2019-09-10 01:34:00.789 UTC</TimeStamp>
<WhereFrom>127.0.0.250</WhereFrom>
</Header>
<Body>
<Teacher>
<ID>1</ID>
<Name>乌云</Name>
</Teacher>
<Grade>
<id>2</id>
<Name>社会一年级</Name>
<Students>
<ID>123</ID>
<FirstName>赵</FirstName>
<LastName>大大</LastName>
<Birthday>2019-09-10</Birthday>
<City>北京</City>
<Age>24</Age>
</Students>
<Students>
<ID>213</ID>
<FirstName>钱</FirstName>
<LastName>大大</LastName>
<Birthday>2019-09-10</Birthday>
<City>上海</City>
<Age>24</Age>
</Students>
<Students>
<ID>321</ID>
<FirstName>薛</FirstName>
<LastName>小小</LastName>
<Birthday>2019-09-10</Birthday>
<City>山西</City>
<Age>24</Age>
</Students>
</Grade>
</Body>
</Request>
Process finished with exit code 0
注意:对于日期类型的字段,需要使用Date类型,如果是String类型,上面的日期类型转换器会报错,以后扩展;上面的日期转化器可以根据需要改成自己的日期格式,将日期格式作为参数进行控制。
七、补充
如果想要在对象中忽略某个字段,可以使用注解 @XStreamOmitField
再说明一点,因为我在公司实际是拿到的首字母什么的是小写的报文,我是先转化为的对象,然后将对象转换为xml;将json转换为对象这个下篇写吧。如果json格式的报文中没有对象中的某个字段,这个时候转化时是不进行转换的,所以上面的那个注解我实际没有用到。搬砖了!