fastjson
转自:https://github.com/ZhongFuCheng3y/athena
一、fastjson入门
以下内容来源:https://github.com/alibaba/fastjson/wiki/Quick-Start-CN
它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean

fastjson优点:速度快、使用广泛、使用简单、功能完备、测试完备(之前爆了很多漏洞,现在我司走发布流程都强制我们升级fastjson版本了),现在使用fastjson至少升级到1.2.60版本
速度快的原因:
1、自行编写类似StringBuilder的工具类SerializeWriter。
2、使用ThreadLocal来缓存buf。
3、使用asm避免反射
4、集成jdk实现的一些优化算法
二、使用fastjson
首先我们在pom文件中引入fastjson的依赖就好了:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>x.x.x</version>
</dependency>
fastjson的使用主要是三个对象:
- JSON
- JSONObject
- JSONArray
JSONArray和JSONObject继承JSON:

2.1 JSON对象
JSON这个类主要用于转换:
- 将Java对象序列化为JSON字符串
- 将JSON字符串反序列化为Java对象
所以,有三个方法我们用得特别多:
parseObject(String text, Class<T> clazz)parseArray(String text, Class<T> clazz)toJSONString(Object object)
2.2 JSONObject
JSON对象( JSONObject )中的数据都是以 key-value 形式出现,所以它实现了 Map 接口:

使用起来也很简单,跟使用 Map 就没多大的区别(因为它底层实际上就是操作 Map ),常用的方法:
getString(String key)remove(Object key)put(String key, Object value)clear()getJSONObject(String key)getJSONArray(String key)

2.3 JSONArray
JSONArray则是JSON数组,JSON数组对象中存储的是一个个JSON对象,所以类中的方法主要用于直接操作JSON对象

最常用的方法:
getJSONObject(int index)
三、序列化和反序列化
从上面的简单介绍我们已经可以知道了:
- JSON用于将字符串反序列化为JavaBean和JavaBean序列化为JSON
- JSONObject代表的是JSON对象,底层通过Map来操作,常用
getString等方法来获取对应的值 - JSONArray代表的是JSON对象数组,底层实际上是List,它用作于操作JSON对象
常用api
// 把JSON文本parse为JSONObject或者JSONArray
public static final Object parse(String text);
// 把JSON文本parse成JSONObject
public static final JSONObject parseObject(String text);
// 把JSON文本parse为JavaBean
public static final <T> T parseObject(String text, Class<T> clazz);
// 把JSON文本parse成JSONArray
public static final JSONArray parseArray(String text);
//把JSON文本parse成JavaBean集合
public static final <T> List<T> parseArray(String text, Class<T> clazz);
// 将JavaBean序列化为JSON文本
public static final String toJSONString(Object object);
// 将JavaBean根据字段特征序列化
public static final String toJSONString(Object object,SerializerFeature... features);
//将JavaBean转换为JSONObject或者JSONArray。
public static final Object toJSON(Object javaObject);
反序列化
一般来说,我们从数据库拿到JSON数据以后,然后要对JSON进行修改。比如JSON串如下:
{
"formId": "{$formId}",
"link": "www.java3y.com",
"text": [{
"name": "java3y",
"label": "3y",
"value": {
"value": "{$tureName}",
"color": "",
"emphasis": ""
}
}, {
"name": "java4y",
"label": "3y",
"value": {
"value": "{$title}",
"color": "",
"emphasis": ""
}
}, {
"name": "java5y",
"label": "5y",
"value": {
"value": "关注我的公众号,更多干货",
"color": "#ff0040",
"emphasis": ""
}
}],
"yyyImg": "",
"yyyAge": "",
"pagepath": ""
}
我们是不会直接操作JSON的,我们会将JSON转成我们自己的JavaBean,再操作JavaBean,最后序列化为JSONString
从上面的JSON结构上来看还是相对复杂的,思路:
- 我们可以根据
JSON的结构构建对应的JavaBean - 使用
JSON类将JSON字符串反序列化为JavaBean - 修改JavaBean的值
- 最后将
JavaBean序列化为JSON字符串
从上面的JSON结构,首先我们针对text这层抽象为一个JavaBean。(实际上最里层的结构是value,但我这边不需要处理value,所以就不抽象了)
/**
* "name": "java3y",
* "label": "3y",
* "value": {
* "value": "{$tureName}",
* "color": "",
* "emphasis": ""
* }
*
* 对Text进行抽象
*/
public class TextInfo {
private String name;
private String label;
// 因为value我这边不需要操作,所以就不抽象了,如果每层都要处理,那就得抽象
private Object value;
// set get ... 省略
}
然后对外层进行抽象:
public class ContentValue {
private String formId;
private String link;
// 这里是一个数组,我们就抽象为List,属性名为text
private List<TextInfo> text;
private String yyyImg;
private String yyyAge;
private String pagepath;
// set get ... 省略
}
我们反序列化看一下:
public static void main(String[] args) {
// JSON 字符串
String s = "{\"formId\":\"{$formId}\",\"link\":\"www.java3y.com\",\"text\":[{\"name\":\"java3y\",\"label\":\"3y\",\"value\":{\"value\":\"{$tureName}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java4y\",\"label\":\"3y\",\"value\":{\"value\":\"{$title}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java5y\",\"label\":\"5y\",\"value\":{\"value\":\"关注我的公众号,更多干货\",\"color\":\"#ff0040\",\"emphasis\":\"\"}}],\"yyyImg\":\"\",\"yyyAge\":\"\",\"pagepath\":\"\"}";
// 使用JSON对象 将JSON字符串反序列化为JavaBean
ContentValue contentValue = JSON.parseObject(s, ContentValue.class);
System.out.println(contentValue);
}
反序列化结果:

我们要改text里边的值,只需要操作JavaBean就好了:
public static void main(String[] args) {
// JSON 字符串
String s = "{\"formId\":\"{$formId}\",\"link\":\"www.java3y.com\",\"text\":[{\"name\":\"java3y\",\"label\":\"3y\",\"value\":{\"value\":\"{$tureName}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java4y\",\"label\":\"3y\",\"value\":{\"value\":\"{$title}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java5y\",\"label\":\"5y\",\"value\":{\"value\":\"关注我的公众号,更多干货\",\"color\":\"#ff0040\",\"emphasis\":\"\"}}],\"yyyImg\":\"\",\"yyyAge\":\"\",\"pagepath\":\"\"}";
// 使用JSON对象 将JSON字符串反序列化为JavaBean
ContentValue contentValue = JSON.parse(s, ContentValue.class);
List<TextInfo> text = contentValue.getText();
for (TextInfo textInfo : text) {
textInfo.setName("Java3y");
textInfo.setLabel("关注我的公众号呗");
}
// 修改后,反序列化回去
String content = JSON.toJSONString(contentValue);
}
序列化结果:

轻松将JSON字符串里边的字段改掉。
parse、parseObejct、parseArray区别
JSON.parseArray() 和 JSON.parseObject 都是讲 json 字符串转为实体类的方法
- JSON.parseArray 用于 json 是 [] 包裹的
- JSON.parseObject 用于 json 是 {} 包裹的
- 用JSON.toJSONString() 来解析对象
JSON.parse() 与 JSON.parseObject() 的区别
两者转化的结果都是一个json对象,没有区别。但是JSON.parseObject生成的对象有许多可以操作的方法,所以后端一般都是JSON.parseObject来解析json字符串
序列化
实体类:
package com.qr;
import lombok.Data;
import java.util.Date;
/**
* FastJson
*/
@Data
public class Student {
private Integer id;
private String name;
private Integer age;
private Date bitrthday;
}
测试
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.junit.Test;
import java.util.*;
public class FastJsonTest {
/**
* java对象转为json格式的字符串
*/
@Test
public void testObjectToJson(){
Student student = new Student();
student.setId(1);
student.setName("list");
student.setAge(11);
student.setBitrthday(new Date());
//转化
String jsongString = JSON.toJSONString(student);
System.out.println(jsongString);
//{"age":11,"bitrthday":1620137932283,"id":1,"name":"list"}
}
/**
* java中的集合转换为json
*/
@Test
public void testListToJson() {
List<Student> list = new ArrayList<Student>();
Student student1 = new Student();
student1.setId(1);
student1.setName("list");
student1.setAge(11);
student1.setBitrthday(new Date());
Student student2 = new Student();
student2.setId(2);
student2.setName("lisa");
student2.setAge(12);
student2.setBitrthday(new Date());
list.add(student1);
list.add(student2);
//list集合序列华为json格式的字符串
String s = JSON.toJSONString(list);
System.out.println(s);
//[{"age":11,"bitrthday":1620138289599,"id":1,"name":"list"},{"age":12,"bitrthday":1620138289599,"id":2,"name":"lisa"}]
}
/**
* map集合
*/
@Test
public void testMapToJson(){
Map<String,Student> map = new HashMap<String, Student>();
Student student1 = new Student();
student1.setId(1);
student1.setName("list");
student1.setAge(11);
student1.setBitrthday(new Date());
Student student2 = new Student();
student2.setId(2);
student2.setName("lisa");
student2.setAge(12);
student2.setBitrthday(new Date());
//map集合存储对象
map.put("stu1",student1);
map.put("stu2",student2);
String s = JSON.toJSONString(map);
System.out.println(s);
// {"stu2":{"age":12,"bitrthday":1620138549606,"id":2,"name":"lisa"},
// "stu1":{"age":11,"bitrthday":1620138549606,"id":1,"name":"list"}}
}
/**
* 反序列化
*/
/**
* json 反序列化为 java对象
*/
@Test
public void testJsonToObject(){
String json = "{\"age\":11,\"bitrthday\":1620137932283,\"id\":1,\"name\":\"list\"}";
Student student = JSON.parseObject(json, Student.class);
System.out.println(student);
//Student(id=1, name=list, age=11, bitrthday=Tue May 04 22:18:52 CST 2021)
}
/**
* json 反序列化为 list集合
*/
@Test
public void testJsonToList(){
String json = "[{\"age\":11,\"bitrthday\":1620138289599,\"id\":1,\"name\":\"list\"},{\"age\":12,\"bitrthday\":1620138289599,\"id\":2,\"name\":\"lisa\"}]";
List<Student> list = JSON.parseArray(json, Student.class);
list.forEach(System.out::println);
/**
* Student(id=1, name=list, age=11, bitrthday=Tue May 04 22:24:49 CST 2021)
* Student(id=2, name=lisa, age=12, bitrthday=Tue May 04 22:24:49 CST 2021)
*/
}
@Test
public void testJsonToMap(){
String json = "{\"stu2\":{\"age\":12,\"bitrthday\":1620138549606,\"id\":2,\"name\":\"lisa\"},\"stu1\":{\"age\":11,\"bitrthday\":1620138549606,\"id\":1,\"name\":\"list\"}}";
//直接反序列化是没有泛型的,转不过去,没有泛型的集合是不安全的
// Map jsonObject = JSON.parseObject(json);
//传入转后的map集合,最后部分需要添加一个括号{}
Map<String, Student> map = JSON.parseObject(json, new TypeReference<Map<String, Student>>(){});
for (String key:map.keySet()){
System.out.println(key+":"+map.get(key));
}
/**
* stu2:Student(id=2, name=lisa, age=12, bitrthday=Tue May 04 22:29:09 CST 2021)
* stu1:Student(id=1, name=list, age=11, bitrthday=Tue May 04 22:29:09 CST 2021)
*/
}
}
序列化特征数组
方法
SerializerFeature[] features = {
SerializerFeature.WriteMapNullValue, // 输出空置字段
SerializerFeature.WriteNullListAsEmpty, // list字段如果为null,输出为[],而不是null
SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而不是null
SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而不是null
SerializerFeature.WriteNullStringAsEmpty, // 字符类型字段如果为null,输出为"",而不是null
};
JSON.toJSONString(object, features);
@Data
public class Student {
private Integer id;
private String name;
private Integer age;
private Date bitrthday;
//添加一个布尔值
private Boolean flag;
}
package com.qr;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.junit.Test;
import java.util.Date;
/**
* SerializerFeature枚举:
* 进行序列化的时候,可以自定义特殊需求
*
*/
public class FastJsonTest2 {
/**
* 序列化为null值的字段
* WriteMapNullValue
*/
@Test
public void testWriteMapNullValue(){
Student student = new Student();
student.setId(1);
student.setName("zhangsan");
student.setAge(20);
// String s = JSON.toJSONString(student);
// System.out.println(s);
//{"age":20,"id":1,"name":"zhangsan"},空值是没有被序列化的
//SerializerFeature.WriteMapNullValue
String s = JSON.toJSONString(student, SerializerFeature.WriteMapNullValue);
System.out.println(s);
//{"age":20,"bitrthday":null,"id":1,"name":"zhangsan"}
}
/**
* 序列化为null的字段,序列化为""
*/
@Test
public void testWriteNullStringEnpty(){
Student student = new Student();
student.setId(1);
student.setAge(20);
String s = JSON.toJSONString(student,SerializerFeature.WriteNullStringAsEmpty);
System.out.println(s);
//{"age":20,"bitrthday":null,"id":1,"name":""}
}
/**
* 序列化为null的number为0
*/
@Test
public void testWriteNullNumberAsZero(){
Student student = new Student();
student.setId(1);
student.setName("zhangsan");
// student.setAge(20);
student.setBitrthday(new Date());
String s = JSON.toJSONString(student,SerializerFeature.WriteNullNumberAsZero);
System.out.println(s);
//{"age":0,"bitrthday":1620141333809,"id":1,"name":"zhangsan"}
}
/**
* WriteNullBooleanAsFalse枚举常量,boolean值为null,序列化为false
*/
@Test
public void testWriteNullBooleanAsFalse(){
Student student = new Student();
student.setId(1);
student.setName("zhangsan");
student.setAge(20);
student.setBitrthday(new Date());
student.setFlag(true);
String s = JSON.toJSONString(student,SerializerFeature.WriteNullBooleanAsFalse);
System.out.println(s);
//{"age":20,"bitrthday":1620141727099,"flag":true,"id":1,"name":"zhangsan"}
}
/**
* 序列化日期格式化
*
*/
@Test
public void testWriteDateUseDateFormatPrettyFormat(){
Student student = new Student();
student.setId(1);
student.setName("zhangsan");
student.setAge(20);
student.setBitrthday(new Date());
student.setFlag(true);
String s = JSON.toJSONString(student,SerializerFeature.WriteDateUseDateFormat);
System.out.println(s);
//{"age":20,"bitrthday":"2021-05-04 23:25:57","flag":true,"id":1,"name":"zhangsan"}
String s2 = JSON.toJSONString(student,SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.PrettyFormat);
System.out.println(s2);
/**
* {
* "age":20,
* "bitrthday":"2021-05-04 23:27:20",
* "flag":true,
* "id":1,
* "name":"zhangsan"
* }
*/
}
}
四、注解
JSONField配置方式
FieldInfo可以配置在getter/setter方法或者字段上。例如:
配置在getter/setter上
public class A {
private int id;
@JSONField(name="ID")
public int getId() {return id;}
@JSONField(name="ID")
public void setId(int value) {this.id = id;}
}
配置在field上
public class A {
@JSONField(name="ID")
private int id;
public int getId() {return id;}
public void setId(int value) {this.id = id;}
}
使用name指定字段名称
当前端传过来的字段名不一样的时候,我们可以在字段名上加上这个注解
public class A {
@JSONField(name="ID")
private int id;
public int getId() {return id;}
public void setId(int value) {this.id = id;}
}
使用format配置日期格式化
public class A {
// 配置date序列化和反序列使用yyyyMMdd日期格式
@JSONField(format="yyyyMMdd")
public Date date;
}
使用serialize/deserialize指定字段不序列化
public class A {
@JSONField(serialize=false)
public Date date;
}
public class A {
@JSONField(deserialize=false)
public Date date;
}
使用ordinal指定字段的顺序
缺省fastjson序列化一个java bean,是根据fieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序。这个特性需要1.1.42以上版本。
public static class VO {
@JSONField(ordinal = 3)
private int f0;
@JSONField(ordinal = 2)
private int f1;
@JSONField(ordinal = 1)
private int f2;
}
使用serializeUsing制定属性的序列化类
在fastjson 1.2.16版本之后,JSONField支持新的定制化配置serializeUsing,可以单独对某一个类的某个属性定制序列化,比如:
public static class Model {
@JSONField(serializeUsing = ModelValueSerializer.class)
public int value;
}
public static class ModelValueSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
int features) throws IOException {
Integer value = (Integer) object;
String text = value + "元";
serializer.write(text);
}
}
演示
package com.qr;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.Date;
/**
* FastJson
*/
@Data
public class Student {
private Integer id;
//注解属性
@JSONField(name = "studentName",ordinal = 1)
private String name;
@JSONField(ordinal = 2,serialize = false)
private Integer age;
@JSONField(format = "yyyy-MM-dd")
private Date bitrthday;
//添加一个布尔值
private Boolean flag;
}
package com.qr;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.junit.Test;
import java.util.Date;
/**
* JSONFeild注解:
* 该注解作用于方法上,字段和参数上,可在序列化和反序列时进行特定功能定制
*/
public class FastJsonTest3 {
/**
* 序列化的时候可以做到修改属性名
*/
@Test
public void testObjectToJson(){
Student student = new Student();
student.setId(1);
student.setName("list");
student.setAge(11);
student.setBitrthday(new Date());
student.setFlag(true);
String jsongString = JSON.toJSONString(student);
System.out.println(jsongString);
/**
* //注解属性
* @JSONField(name = "studentName")
* private String name;
*
* {"age":11,"bitrthday":1620142567227,"flag":true,"id":1,"studentName":"list"}
*/
/**
* 可以改变出现的位置
* @JSONField(name = "studentName",ordinal = 1)
* private String name;
* @JSONField(ordinal = 2)
* private Integer age;
* 注解的顺序可以进行调整
* {"bitrthday":1620142775049,"flag":true,"id":1,"studentName":"list","age":11}
*/
/**
* @JSONField(format = "yyyy-MM-dd")
* private Date bitrthday;
* {"bitrthday":"2021-05-04","flag":true,"id":1,"studentName":"list","age":11}
*/
/**
* @JSONField(ordinal = 2,serialize = false)指定false就不会进行序列化
* private Integer age;
* {"bitrthday":"2021-05-04","flag":true,"id":1,"studentName":"list"}
*/
}
}
JSONType
@Data
//includes指的是要被序列化的字段
@JSONType(includes = {"id","age","address"})
public class Person {
private Integer id;
private String name;
private Integer age;
private String address;
}
/**
* JSONType注解:
* 该注解作用于方法上,字段和参数上,可在序列化和反序列时进行特定功能定制
*/
public class FastJsonTest4 {
@Test
public void test(){
Person person = new Person();
person.setId(1);
person.setName("aa");
person.setAge(11);
person.setAddress("浙江杭州");
String s = JSON.toJSONString(person);
System.out.println(s);
//{"address":"浙江杭州","age":11,"id":1}name没有被序列化
}
}
@Data
//includes指的是要被序列化的字段
//orders明确序列化后的顺序
@JSONType(includes = {"id","name","age","address"},orders = {"name","address","age","id"})
public class Person {
private Integer id;
private String name;
private Integer age;
private String address;
}
public class FastJsonTest4 {
@Test
public void test(){
Person person = new Person();
person.setId(1);
person.setName("aa");
person.setAge(11);
person.setAddress("浙江杭州");
String s = JSON.toJSONString(person);
System.out.println(s);
//{"name":"aa","address":"浙江杭州","age":11,"id":1}
}
}

浙公网安备 33010602011771号