文章目录
JSON回顾
FastJson介绍
FastJson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串
支持将 Java Bean 序列化为 JSON 字符串
也可以从 JSON 字符串反序列化到 JavaBean
。
Fastjson 的优点
- 速度快
fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。 - 使用广泛
fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。 - 测试完备
fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。 - 使用简单
fastjson的 API 十分简洁。 - 功能完备
支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。
依赖引入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
JSON抽象类、JSONObject类、JSONArray类
JSON类是JSONObject和JSONArray的父类
JSON类常用方法
public abstract class JSON implements JSONStreamAware, JSONAware
-
parseObject方法
: 解析为对象(反序列化)
-
parseArray方法
: 解析为集合 -
toJSONString方法
: 转为JSON格式的字符串(序列化)
-
toJavaObject方法
: JSON对象转为Java对象 -
public static String
toJSONStringWithDateFormat
(Object object, String dateFormat,SerializerFeature… features)@Test public void testDateFormart() { String dateStr = JSON.toJSONStringWithDateFormat(new Date(), "yyyy-MM-dd"); System.out.println(dateStr); // "2022-08-15" }
JSONObject类常用方法
public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler
- 由于JSONObject继承JSON类, 所以JSON抽象类的公共方法也能够使用
- 还继承了Map, 也拥有Map的一些方法
-
public JSONObject getJSONObject(int index)
: 根据JSONArray的索引index, 生成JSONObject对象 -
public JSONArray getJSONArray(int index)
: 根据JSONArray的索引index, 生成JSON类型的数组 -
public T getXxx(int index)
: 根据JSONArray的index, 获取该index的value
JSONArray类常用方法
public class JSONArray extends JSON implements List, Cloneable, RandomAccess, Serializable
- 由于JSONArray继承JSON类, 所以JSON抽象类的公共方法也能够使用
- 也继承了List接口, 拥有List的一些方法
-
public JSONObject getJSONObject(String key)
: 根据JSON的key, 生成JSONObject对象 -
public JSONArray getJSONArray(String key)
: 根据JSON的key, 生成JSON类型的数组 -
public T getXxx(String key)
: 根据JSON的key, 获取该key的value
FastJson的使用
FastJson序列化API
序列化
: 把Java对象转换为字节序列(JSON字符串)的过程。
-
JSON.toJSONString
- 序列化Java对象
public void objectToJson(){ Student student = new Student(); student.setId(1); student.setName("张三"); student.setAge(20); student.setAddress("北京市"); student.setEmail("zs@sina.com"); String jsonString = JSON.toJSONString(student); System.out.println(jsonString); }
- 序列化List集合
public void listToJson(){ Student student = new Student(); student.setId(1); student.setName("张三"); student.setAge(20); student.setAddress("北京市"); student.setEmail("zs@sina.com"); Student student2 = new Student(); student2.setId(2); student2.setName("张三2"); student2.setAge(22); student2.setAddress("北京市2"); student2.setEmail("zs2@sina.com"); List<Student> list = new ArrayList<Student>(); list.add(student); list.add(student2); String jsonString = JSON.toJSONString(list); System.out.println(jsonString); }
- 序列化Map集合
public void mapToJson(){ Student student = new Student(); student.setId(1); student.setName("张三"); student.setAge(20); student.setAddress("北京市"); student.setEmail("zs@sina.com"); Student student2 = new Student(); student2.setId(2); student2.setName("张三2"); student2.setAge(22); student2.setAddress("北京市2"); student2.setEmail("zs2@sina.com"); Map<String,Student> map = new HashMap<String, Student>(); map.put("s1",student); map.put("s2",student2); String jsonString = JSON.toJSONString(map); System.out.println(jsonString); }
FashJson反序列化API
反序列化
: 把字节序列(JSON字符串)恢复为Java对象的过程
-
JSON.parseObject
- 反序列化Java对象
public void jsonToObject(){ String jsonString = "{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"}"; Student student = JSON.parseObject(jsonString, Student.class); System.out.println(student); }
-
JSON.parseArray
- 反序列化List集合
public void jsonToList(){ String jsonString = "[{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"},{\"address\":\"北京市2\",\"age\":22,\"email\":\"zs2@sina.com\",\"id\":2,\"name\":\"张三2\"}]"; List<Student> list = JSON.parseArray(jsonString,Student.class); for (int i = 0; i < list.size(); i++) { Student student = list.get(i); System.out.println(student); } }
-
JSON.parseObject
- 反序列化Map集合
public void jsonToMap(){ String jsonString = "{\"s1\":{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"},\"s2\":{\"address\":\"北京市2\",\"age\":22,\"email\":\"zs2@sina.com\",\"id\":2,\"name\":\"张三2\"}}"; Map<String,Student> parse = JSON.parseObject(jsonString,new TypeReference<Map<String,Student>>(){}); for(String s : parse.keySet()){ System.out.println(s + ":::"+parse.get(s)); } }
Java对象 转 JSON串、JSON对象
Java对象–>JSON串
String jsonStr = JSONObject.toJSONString(Java对象实例)
@Test
public void javaObj2JsonStr() {
Student student = Student.builder().name("lucky").age(22).build();
//String jsonString = JSON.toJSONString(student);
String jsonString = JSONObject.toJSONString(student);
System.out.println(jsonString); // {"age":22,"name":"lucky"}
}
Java对象–>JSON对象
JSONObject jsonObj = (JSONObject) JSONObject.toJSON(Java对象实例)
@Test
public void javaObj2JsonObj() {
Student student = Student.builder().name("lucky").age(22).build();
Object obj = JSONObject.toJSON(student);
JSONObject jsonObject = (JSONObject) obj;
System.out.println(jsonObject); // {"name":"lucky","age":22}
String name = jsonObject.getString("name");
Integer age = jsonObject.getInteger("age");
System.out.printf("name: %s, age: %d", name, age); // name: lucky, age: 22
}
JSON串 转 Java对象、JSON对象
JSON串–>Java对象
T obj = JSONObject.parseObject(JSON字符串, Java对象.class);
@Test
public void jsonStr2JavaObj() {
String stuStr = "{\"age\":22,\"name\":\"lucky\"}";
Student student = JSONObject.parseObject(stuStr, Student.class);
System.out.println(student); // Student(name=lucky, age=22)
}
JSON串–>JSON对象
JSONObject jsonObj = JSONObject.parseObject(JSON字符串)
@Test
public void jsonStr2JsonObj() {
String stuStr = "{\"age\":22,\"name\":\"lucky\"}";
JSONObject jsonObject = JSONObject.parseObject(stuStr);
System.out.println(jsonObject); // {"name":"lucky","age":22}
String name = jsonObject.getString("name");
Integer age = jsonObject.getInteger("age");
System.out.printf("name: %s, age: %d", name, age); // name: lucky, age: 22
}
JSON对象 转 Java对象、JSON串
JSON对象–>Java对象
T obj = JSONObject.toJavaObject(JSON对象实例, Java对象.class);
@Test
public void jsonObj2JavaObj() {
Student student = Student.builder().name("lucky").age(22).build();
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(student);
Student stu2 = jsonObject.toJavaObject(Student.class);
System.out.println(stu2); // Student(name=lucky, age=22)
}
JSON对象–>JSON串
String jsonStr = JSONObject.toJSONString();
@Test
public void jsonObj2JsonStr() {
Student student = Student.builder().name("lucky").age(22).build();
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(student);
String jsonStr = jsonObject.toJSONString();
System.out.println(jsonStr); // {"age":22,"name":"lucky"}
}
JSON字符串 转 List
List<?> parseArray(JSON字符串, Java对象.class)
@Test
public void jsonStr2List() {
String jsonStr = "[{\"name\":\"lucky\",\"age\":22}, {\"name\":\"Tom\",\"age\":33}]";
List<Student> students = JSONObject.parseArray(jsonStr, Student.class);
students.forEach(System.out::println);
/*
输出
Student(name=lucky, age=22)
Student(name=Tom, age=33)
*/
}
JSON字符串 转 Map
Map<String, String> mapObj = JSONObject.parseObject(jsonStr, new TypeReference<Map<String, String>>() {
})
@Test
public void jsonStr2Map() {
Map<String, String> map = new HashMap<>() {{
put("name", "lucky");
put("age", "22");
}};
String mapStr = JSONObject.toJSONString(map);
System.out.println(mapStr); // {"name":"lucky","age":"22"}
//Map<String, String> mapObj = (Map<String, String >) JSON.parse(mapStr)
Map<String, String> mapObj = JSONObject.parseObject(mapStr, new TypeReference<Map<String, String>>() {
});
System.out.println(mapObj); // {name=lucky, age=22}
}
泛型反序列化
- import com.alibaba.fastjson.TypeReference;
List<T> list = JSON.parseObject("...", new TypeReference<List<VO>>() {});
SerializerFeature枚举
该枚举支持序列化的一些特性数据定义:
- 枚举常量 WriteMapNullValue 序列化为null的字段
- 枚举常量 WriteNullStringAsEmpty 字段为null,序列化为""
- 枚举常量 WriteNullNumberAsZero 字段为null,序列化为0
- 枚举常量 PrettyFormat格式化输出
- 枚举常量 WriteNullBooleanAsFalse 字段值为null 输出false
- 枚举常量 WriteDateUseDateFormat 格式化日期格式
// 测试类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private String name;
private Integer age;
private String address;
}
测试
public class JSONFieldTest {
@Test
public void testSerializerFeature() {
Student stu = Student.builder().age(20).address("上海").build();
String stuJson = JSON.toJSONString(stu);
System.out.println("stuJson = " + stuJson); // stuJson = {"address":"上海","age":20}
String stuJson2 = JSON.toJSONString(stu, SerializerFeature.WriteMapNullValue);
System.out.println("stuJson2 = " + stuJson2); // stuJson2 = {"address":"上海","age":20,"name":null}
String stuJson3 = JSON.toJSONString(stu, SerializerFeature.WriteNullStringAsEmpty);
System.out.println("stuJson3 = " + stuJson3); // stuJson3 = {"address":"上海","age":20,"name":""}
Student stu2 = Student.builder().name("lucky").address("上海").build();
String stu2Json = JSON.toJSONString(stu2, SerializerFeature.WriteNullNumberAsZero);
System.out.println("stu2Json = " + stu2Json); // stu2Json = {"address":"上海","age":0,"name":"lucky"}
String stu2Json2 = JSON.toJSONString(stu2, SerializerFeature.PrettyFormat);
System.out.println("stu2Json = " + stu2Json2);
// 输出
/*
stuJson = {"address":"上海","age":20}
stuJson2 = {"address":"上海","age":20,"name":null}
stuJson3 = {"address":"上海","age":20,"name":""}
stu2Json = {"address":"上海","age":0,"name":"lucky"}
stu2Json = {
"address":"上海",
"name":"lucky"
}
*/
}
}
@JSONField注解
注意:若属性是私有的,必须有set方法。否则无法反序列化。
该注解作用于方法上,字段上和参数上, 可在序列化和反序列化时进行特性功能定制.
- 注解属性 : name 序列化后的名字
- 注解属性 : ordinal序列化后的顺序
- 注解属性 : format 序列化后的格式, 对日期格式有用
- 注解属性 : serialize 是否序列化该字段
- 注解属性 : deserialize 是否反序列化该字段
- 注解属性 : serialzeFeatures 序列化时的特性定义
1. @JSONField配置方式, 使用name属性
可以配置在Field上, 或者getter/setter方法上
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
@JSONField(name = "NAME")
private String name;
private Integer age;
}
测试
@Test
public void testJSONFieldName() {
Student stu = Student.builder().name("lucky").age(20).build();
// 序列化后的JSON中key的名字
String stuStr = JSON.toJSONString(stu);
System.out.println("stuStr = " + stuStr); // stuStr = {"NAME":"lucky","age":20}
// 通过@FieldName(name="xxx"),可以将JSON串中xxx,反序列化给标注注解的字段
Student stuObj = JSONObject.parseObject(stuStr, Student.class);
System.out.println("stuObj = " + stuObj); // stuObj = Student(name=lucky, age=20)
}
//输出:
//stuStr = {"NAME":"lucky","age":20}
//stuObj = Student(name=lucky, age=20)
2. 使用format配置日期格式化
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
// 配置date序列化和反序列使用yyyy-MM-dd日期格式
@JSONField(format="yyyy-MM-dd")
private Date date;
}
测试
@Test
public void testJSONFieldFormat() {
Student stu = Student.builder().date(new Date()).build();
String jsonStu = JSONObject.toJSONString(stu);
System.out.println("jsonStu = " + jsonStu); // jsonStu = {"date":"2022-08-15"}
}
//输出
//jsonStu = {"date":"2022-08-15"}
3. 使用serialize/deserialize指定字段是否序列化
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
// 不进行反序列化
@JSONField(name = "NAME", deserialize = false)
private String name;
// 不进行序列化
@JSONField(name = "AGE", serialize = false)
private Integer age;
@JSONField(format = "yyyy/MM/dd")
private Date date;
}
测试
@Test
public void testIsSerializeAndDeSerialize() {
Student stuObj = Student.builder().name("lucky").age(22).date(new Date()).build();
String stuJson = JSONObject.toJSONString(stuObj);
System.out.println("stuJson = " + stuJson); // stuJson = {"NAME":"lucky","date":"2022/08/16"}
Student stuObj2 = JSON.parseObject(stuJson, Student.class);
System.out.println("stuObj2 = " + stuObj2);
}
//输出:
//stuJson = {"NAME":"lucky","date":"2022/08/16"}
//stuObj2 = Student(name=null, age=null, date=Tue Aug 16 00:00:00 CST 2022)
4. 使用ordinal指定字段的顺序 (序列化)
缺省fastjson序列化一个java bean,是根据FieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序。这个特性需要1.1.42以上版本。
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
@JSONField(name = "NAME")
private String name;
@JSONField(name = "AGE")
private Integer age;
private Double salary;
}
测试
@Test
public void testJSONFieldOrdinal() {
Student stuObj = Student.builder().name("lucky").age(22).salary(999D).build();
// 正常字段的序列化顺序(根据字段首字母的顺序)
String stuJson = JSON.toJSONString(stuObj);
System.out.println("stuJson = " + stuJson); // stuJson = {"AGE":22,"NAME":"lucky","salary":999.0}
Student stu = JSON.parseObject(stuJson, Student.class);
System.out.println("stu = " + stu); // stu = Student(name=lucky, age=22, salary=999.0)
// 输出
// stuJson = {"AGE":22,"NAME":"lucky","salary":999.0}
// stu = Student(name=lucky, age=22, salary=999.0)
}
使用ordinal属性
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
@JSONField(name = "NAME", ordinal = 2)
private String name;
@JSONField(name = "AGE", ordinal = 1)
private Integer age;
@JSONField(ordinal = 0)
private Double salary;
}
测试
@Test
public void testJSONFieldOrdinal() {
Student stuObj = Student.builder().name("lucky").age(22).salary(999D).build();
// 正常字段的序列化顺序(根据字段首字母的顺序)
String stuJson = JSON.toJSONString(stuObj);
System.out.println("stuJson = " + stuJson);
Student stu = JSON.parseObject(stuJson, Student.class);
System.out.println("stu = " + stu);
// 输出
//stuJson = {"salary":999.0,"AGE":22,"NAME":"lucky"}
//stu = Student(name=lucky, age=22, salary=999.0)
}
5. 使用serializeUsing制定属性的序列化类
在fastjson 1.2.16版本之后,JSONField支持新的定制化配置serializeUsing,可以单独对某一个类的某个属性定制序列化,比如:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
@JSONField(serializeUsing = CustomedSalarySerializer.class)
private Double salary;
}
public class CustomedSalarySerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
Double salary = (Double) object;
String salaryStr = salary + "元";
serializer.write(salaryStr);
}
}
测试代码
@Test
public void testJSONFieldSerializeUsing() {
Student stuObj = Student.builder().salary(999.2D).build();
String stuJson = JSONObject.toJSONString(stuObj);
System.out.println("stuJson = " + stuJson);
// 输出
// stuJson = {"salary":"999.2元"}
}
6. JSONField alternateNames
在fastjson在1.2.21版本中提供了一个借鉴自gson的特性,支持反序列化时使用多个不同的字段名称,使用的方式是配置JSONField的alternateNames。
@Data
@NoArgsConstrustor
@AllArgsConstrustor
public class Student {
private int id;
@JSONField(alternateNames = {"user", "person"})
private String name;
}
测试
@Test
public void testJSONFieldAlternateNames() {
String jsonVal0 = "{\"id\":5001,\"name\":\"Jobs\"}";
String jsonVal1 = "{\"id\":5382,\"user\":\"Mary\"}";
String jsonVal2 = "{\"id\":2341,\"person\":\"Bob\"}";
Student obj0 = JSON.parseObject(jsonVal0, Student.class);
Assert.assertEquals(5001, obj0.getId());
Assert.assertEquals("Jobs", obj0.getName()); // true
Student obj1 = JSON.parseObject(jsonVal1, Student.class);
Assert.assertEquals(5382, obj1.getId());
Assert.assertEquals("Mary", obj1.getName()); // true
Student obj2 = JSON.parseObject(jsonVal2, Student.class);
Assert.assertEquals(2341, obj2.getId());
Assert.assertEquals("Bob", obj2.getName()); // true
}
7. JSONField jsonDirect
在fastjson-1.2.12版本中,JSONField支持一个新的配置项jsonDirect,它的用途是:当你有一个字段是字符串类型,里面是json格式数据,你希望直接输入,而不是经过转义之后再输出。
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private int id;
@JSONField(jsonDirect = true)
private String other;
}
测试
@Test
public void testJSONFieldJsonDirect() {
Student stu = Student.builder().id(1001).other("{\"name\":\"lucky\"}").build();
String stuJSON = JSON.toJSONString(stu);
System.out.println("stuJSON = " + stuJSON);
// 不加 @JSONField(jsonDirect = true) 输出: stuJSON = {"id":1001,"other":"{\"name\":\"lucky\"}"}
// 加 @JSONField(jsonDirect = true) 输出: stuJSON = {"id":1001,"other":{"name":"lucky"}}
}
@ JSONType注解
该注解作用于类上 , 对该类的字段进行序列化和反序列化时的特性功能定制.
- 注解属性 : includes 要被序列化的字段.
- 注解属性 : ignores 不要被序列化的字段.
- 注解属性 : orders 序列化后的顺序.
- 注解属性 : serialzeFeatures 序列化时的特性定义.
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@JSONType(includes = {"name", "sex"}) //序列化只序列化这两个属性成员变量
public class Student {
private int id;
private String name;
private String sex;
private String password;
private String phone;
}
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@JSONType(ignores = {"id", "sex"}) //不序列化这两个成员变量
public class Student2 {
private int id;
private String name;
private String sex;
private String password;
private String phone;
}
测试
@Test
public void testFieldType() {
Student stu1 = new Student();
stu1.setId(11).setName("名字1").setPassword("123456").setPhone("13502141419").setSex("男");
String stuJson1 = JSON.toJSONString(stu1);
System.out.println("stuJson1 = " + stuJson1);
Student2 stu2 = new Student2();
stu2.setId(11).setName("名字1").setPassword("123456").setPhone("13502141419").setSex("男");
String stuJson2 = JSON.toJSONString(stu2);
System.out.println("stuJson2 = " + stuJson2);
// 输出
// stuJson1 = {"name":"名字1","sex":"男"}
// stuJson2 = {"name":"名字1","password":"123456","phone":"13502141419"}
}