fastjson用于将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
主要就以下几点做个介绍
- SerializerFeature特性的使用
- JSONField与JSONType注解的使用
- SerializeFilter
- 泛型反序列化
- fastjson各种概念
简单使用
通过maven引入相应的json包
1
2
3
4
5
6
7<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
</dependencies>定义一个需要转换所实体类User,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.ohaotian.feifz.style.study.utils.fastjson;
/**
* @author feifz
* @version 1.0.0
* @Description 研究fastjson用到的对象
* @createTime 2019年06月10日 16:36:00
*/
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.Date;
public class User {
private Long id;
private String name;
"yyyy-MM-dd HH:mm:ss") (format =
private Date createTime;
}写个简单的测试类用于测试fastjson的序列化与反序列化,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package com.ohaotian.feifz.style.study.utils.fastjson;
/**
* @author feifz
* @version 1.0.0
* @Description fastjson简单使用
* @createTime 2019年06月10日 16:37:00
*/
import com.alibaba.fastjson.JSON;
import java.util.Date;
public class SimpleTest {
public static void main(String[] args) {
serialize();
deserialize();
}
public static void serialize() {
User user = new User();
user.setId(11L);
user.setName("西安");
user.setCreateTime(new Date());
String jsonString = JSON.toJSONString(user, true);
System.out.println(jsonString);
}
public static void deserialize() {
String jsonString = "{\"createTime\":\"2018-08-17 14:38:38\",\"id\":11,\"name\":\"西安\"}";
User user = JSON.parseObject(jsonString, User.class);
System.out.println(user.getName());
System.out.println(user.getCreateTime());
}
}
SerializerFeature特性的使用
fastjson通过SerializerFeature对生成的json格式的数据进行一些定制,比如可以输入的格式更好看,使用单引号而非双引号等。例子程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.ohaotian.feifz.style.study.utils.fastjson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.Date;
/**
* @author feifz
* @version 1.0.0
* @Description SerializerFeature特性的使用
* @createTime 2019年06月10日 16:40:00
*/
public class SerializerFeatureTest {
public static void main(String[] args) {
User user = new User();
user.setId(11L);
user.setCreateTime(new Date());
String jsonString = JSON.toJSONString(user, SerializerFeature.PrettyFormat,
SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.UseSingleQuotes);
System.out.println(jsonString);
}
}
输出的结果如下:1
2
3
4
5{
'createTime':'2019-06-10 17:25:34',
'id':11,
'name':''
}
SerializerFeature常用属性
名称 | 含义 |
---|---|
QuoteFieldNames | 输出key时是否使用双引号,默认为true |
UseSingleQuotes | 使用单引号而不是双引号,默认为false |
WriteMapNullValue | 是否输出值为null的字段,默认为false |
WriteEnumUsingToString | Enum输出name()或者original,默认为false |
UseISO8601DateFormat | Date使用ISO8601格式输出,默认为false |
WriteNullListAsEmpty | List字段如果为null,输出为[],而非null |
WriteNullStringAsEmpty | 字符类型字段如果为null,输出为”“,而非null |
WriteNullNumberAsZero | 数值字段如果为null,输出为0,而非null |
WriteNullBooleanAsFalse | Boolean字段如果为null,输出为false,而非null |
SkipTransientField | 如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true |
SortField | 按字段名称排序后输出。默认为false |
WriteTabAsSpecial | 把\t做转义输出,默认为false不推荐设为true |
PrettyFormat | 结果是否格式化,默认为false |
WriteClassName | 序列化时写入类型信息,默认为false。反序列化是需用到 |
DisableCircularReferenceDetect | 消除对同一对象循环引用的问题,默认为false |
WriteSlashAsSpecial | 对斜杠’/’进行转义 |
BrowserCompatible | 将中文都会序列化为\uXXXX格式,字节数会多一些,但是能兼容IE 6,默认为false |
WriteDateUseDateFormat | 全局修改日期格式,默认为false。 |
DisableCheckSpecialChar | 一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false |
BeanToArray | 将对象转为array输出 |
JSONField与JSONType注解的使用
注意和@JSONField不同的是,@JSONType是配置在类上的,而@JSONField是配置在字段和方法上的。
JSONField注解的使用
fastjson提供了JSONField对序列化与反序列化进行定制,比如可以指定字段的名称,序列化的顺序。JSONField用于属性,方法方法参数上。JSONField的源码如下:
1 | package com.alibaba.fastjson.annotation; |
属性
name
通过在注解@JSONField指定属性name可以指定该属性在序列化和反序列化过程中输出的key。可作用于Field上,也可作用于setter和setter方法上。
一、作用Field (相当于get set的总和)
@JSONField作用在Field时,其name不仅定义了输入key的名称,同时也定义了输出的名称。
二、作用在setter和getter方法上
顾名思义,当作用在setter方法上时,就相当于根据name到json中寻找对应的值,并调用该setter对象赋值。
当作用在getter上时,在bean转换为json时,其key值为name定义的值。
示例如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69package com.ohaotian.feifz.style.study.utils.fastjson;
/**
* @author feifz
* @version 1.0.0
* @Description JSONField注解 name属性用法
* @createTime 2019年06月11日 14:00:00
*/
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
public class JsonFieldNameDemo {
"jsonName") (name =
private String name;
private String age;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
"jsonAge") (name =
public String getAge() {
return age;
}
"jsonAge") (name =
public void setAge(String age) {
this.age = age;
}
public String getEmail() {
return email;
}
"jsonEmail") (name =
public void setEmail(String email) {
this.email = email;
}
public String toString() {
return "JsonFieldNameDemo [name=" + name + ", age=" + age + ", email="
+ email + "]";
}
public static void main(String[] args) {
JsonFieldNameDemo jsonFieldNameDemo = new JsonFieldNameDemo();
jsonFieldNameDemo.setAge("21岁");
jsonFieldNameDemo.setEmail("111@11.com");
jsonFieldNameDemo.setName("hhh");
System.out.println(JSON.toJSONString(jsonFieldNameDemo));
//输出了:{"jsonName":"hhh","jsonAge":"21岁","email":"111@11.com"}
String json = "{\"email\":\"111@11.com\",\"jsonAge\":\"21岁\",\"jsonName\":\"hhh\"}";
JsonFieldNameDemo jsonTest = JSON.parseObject(json, JsonFieldNameDemo.class);
System.out.println(jsonTest.toString());
}
}
输出结果如下:1
2{"email":"111@11.com","jsonAge":"21岁","jsonName":"hhh"}
JsonFieldNameDemo [name=hhh, age=21岁, email=null]
serialize,deserialize
serialize:是否序列化,默认值都为true,指定为false时序列化过程中不序列化该字段。
deserialize:是否反序列化,默认值都为true,指定为false时反序列化过程中不反序列化该字段
示例代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67package com.ohaotian.feifz.style.study.utils.fastjson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
/**
* @author feifz
* @version 1.0.0
* @Description @JSONField name属性示例
* @createTime 2019年06月11日 14:09:00
*/
public class JsonFieldNameDemo {
private String name;
false) (deserialize =
private String age;
false) (serialize =
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String toString() {
return "JsonFieldNameDemo{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", email='" + email + '\'' +
'}';
}
public static void main(String[] args) {
JsonFieldNameDemo jsonFieldNameTest1 = new JsonFieldNameDemo();
jsonFieldNameTest1.setAge("18");
jsonFieldNameTest1.setEmail("123@163.com");
jsonFieldNameTest1.setName("Bob");
System.out.println(JSON.toJSONString(jsonFieldNameTest1));
String json = "{\"age\":\"18\",\"email\":\"123@163.com\",\"name\":\"Bob\"}";
JsonFieldNameDemo jsonFieldNameTest2 = JSON.parseObject(json, JsonFieldNameDemo.class);
System.out.println(jsonFieldNameTest2.toString());
}
}
输出结果如下:1
2{"age":"18","name":"Bob"}
JsonFieldNameDemo{name='Bob', age='null', email='123@163.com'}
serializeUsing,deserializeUsing
其中serializeUsing与deserializeUsing可以用于对字段的序列化与反序列化进行定制化。比如我们在User实体上加上个sex属性,类型为boolean。下面分别定义了序列化类与反序列化类。
序列化类代码如下:
1 | package com.ohaotian.feifz.style.study.utils.fastjson; |
反序列化类代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37package com.ohaotian.feifz.style.study.utils.fastjson;
/**
* @author feifz
* @version 1.0.0
* @Description TODO
* @createTime 2019年06月11日 10:24:00
*/
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import java.lang.reflect.Type;
public class SexDeserialize implements ObjectDeserializer {
public <T> T deserialze(DefaultJSONParser parser,
Type type,
Object fieldName) {
String sex = parser.parseObject(String.class);
if ("男".equals(sex)) {
return (T) Boolean.TRUE;
} else {
return (T) Boolean.FALSE;
}
}
public int getFastMatchToken() {
return JSONToken.UNDEFINED;
}
}
在定义bean对象时在字段sex上加上注解如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package com.ohaotian.feifz.style.study.utils.fastjson;
/**
* @author feifz
* @version 1.0.0
* @Description 研究fastjson用到的对象
* @createTime 2019年06月10日 16:36:00
*/
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.Date;
public class User {
private Long id;
private String name;
"yyyy-MM-dd HH:mm:ss") (format =
private Date createTime;
(serializeUsing = SexSerializer.class, deserializeUsing = SexDeserialize.class)
private Boolean sex;
}
这样在执行下面代码之后就会发现对sex字段的值定制化了1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38package com.ohaotian.feifz.style.study.utils.fastjson;
/**
* @author feifz
* @version 1.0.0
* @Description fastjson简单使用
* @createTime 2019年06月10日 16:37:00
*/
import com.alibaba.fastjson.JSON;
import java.util.Date;
public class SimpleTest {
public static void main(String[] args) {
serialize();
deserialize();
}
public static void serialize() {
User user = new User();
user.setId(11L);
user.setName("西安");
user.setSex(false);
user.setCreateTime(new Date());
String jsonString = JSON.toJSONString(user, true);
System.out.println(jsonString);
}
public static void deserialize() {
String jsonString = "{\"createTime\":\"2018-08-17 14:38:38\",\"id\":11,\"name\":\"西安\",\"sex\":\"男\"}";
User user = JSON.parseObject(jsonString, User.class);
System.out.println(user.getSex());
System.out.println(user.getName());
System.out.println(user.getCreateTime());
}
}
输出的结果如下:1
2
3
4
5
6
7
8
9{
"createTime":"2019-06-11 11:20:08",
"id":11,
"name":"西安",
"sex":"女"
}
true
西安
Fri Aug 17 14:38:38 CST 2018
JSONType注解的使用
fastjosn提供了JSONType用于类级别的定制化, JSONType的源码如下:
源码
1 | package com.alibaba.fastjson.annotation; |
属性
- includes
序列化时,只序列化这些字段
使用示例:@JSONType(includes = {“name”,”age”}) - ignores
序列化时,忽略这些字段
使用示例:@JSONType(ignores = {“email”}) - orders
序列化时,按照指定的顺序输出结果
使用示例:@JSONType(orders = {“name”,”age”})
使用示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68package com.ohaotian.feifz.style.study.utils.fastjson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONType;
/**
* @author feifz
* @version 1.0.0
* @Description @JSONType 注解使用示例
* @createTime 2019年06月11日 14:41:00
*/
"name","age"},ignores = {"email"},orders = {"name","age"}) (includes = {
public class JsonTypeDemo {
private String name;
private String age;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public JsonTypeDemo(String name, String age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
public String toString() {
return "JsonTypeDemo{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", email='" + email + '\'' +
'}';
}
public static void main(String[] args) {
JsonTypeDemo demo = new JsonTypeDemo("Mary","17","123@163.com");
System.out.println(JSON.toJSONString(demo));
String json = "{\"age\":\"17\",\"email\":\"123@163.com\",\"name\":\"Mary\"}";
JsonTypeDemo jsonTypeDemo = JSON.parseObject(json,JsonTypeDemo.class);
System.out.println(jsonTypeDemo.toString());
}
}
输出结果如下:1
2{"name":"Mary","age":"17"}
JsonTypeDemo{name='Mary', age='17', email='123@163.com'}
SerializeFilter
泛型反序列化
1 | ``` |
反序列化相关的概念
ParserConfig:内部通过一个map保存各种ObjectDeserializer。
JSONLexer : 与SerializeWriter相对应,用于解析json字符串。
JSONToken:定义了一系统的特殊字符,这些称为token。
ParseProcess :定制反序列化,类似于SerializeFilter。
Feature:用于定制各种反序列化的特性。
DefaultJSONParser:相当于反序列化组合器,集成了ParserConfig,Feature, JSONLexer 与ParseProcess。
反序列化的入口代码如下,上面的概念基本都包含了:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37"unchecked") (
public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
int featureValues, Feature... features) {
if (input == null) {
return null;
}
if (features != null) {
for (Feature feature : features) {
featureValues |= feature.mask;
}
}
DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
if (processor != null) {
if (processor instanceof ExtraTypeProvider) {
parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
}
if (processor instanceof ExtraProcessor) {
parser.getExtraProcessors().add((ExtraProcessor) processor);
}
if (processor instanceof FieldTypeResolver) {
parser.setFieldTypeResolver((FieldTypeResolver) processor);
}
}
T value = (T) parser.parseObject(clazz, null);
parser.handleResovleTask(value);
parser.close();
return (T) value;
}