fastjson 使用@JSONType可以實現定制序列化


本文主要詳細介紹一下FastJson使用@JSONField、@JSONType、SerializeFilter進行序列化。之前了解的序列化都是非定制化的,本文介紹的fastjson可以按需求進行定制化輸出。
  本文使用的fastjson版本為1.2.47

FastJson使用@JSONField、@JSONType、SerializeFilter進行序列化時,強調所有的操作(注解)都是在序列化和反序列化的時候起左右(並且該對象也參與其中),其它的時候不起作用(比如對象.get或.set時候沒作用)

1.@JSONField

1.1@JSONField注解代碼演示

這個注解可以設置的參數有:ordinal,name,format,serialize,deserialize,jsonDirect等等,后面的不常用啊
對象AAAaaa類:

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class AAAaaa {

@JSONField(name = "userName", ordinal = 2)
private String name;
private Integer age;
private String address;
@JSONField(name = "userWork", ordinal = 1, serialize = false)
private String work;
@JSONField(name = "userSchool", ordinal = 4, deserialize = false)
private String school;
@JSONField(name = "json", ordinal = 4, jsonDirect = true)
private String studentjson;
//yyyy年MM月dd日 HH時mm分ss秒
@JSONField(ordinal = 3, name = "time", format = "yyyy-MM-dd HH:mm:ss")
private Date createtime;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@JSONField(name = "userAge")
public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getAddress() {
return address;
}

@JSONField(name = "userAddress")
public void setAddress(String address) {
this.address = address;
}

public String getWork() {
return work;
}

public void setWork(String work) {
this.work = work;
}

public String getSchool() {
return school;
}

public void setSchool(String school) {
this.school = school;
}

public String getStudentjson() {
return studentjson;
}

public void setStudentjson(String studentjson) {
this.studentjson = studentjson;
}

public Date getCreatetime() {
return createtime;
}

public void setCreatetime(Date createtime) {
this.createtime = createtime;
}

public AAAaaa() {
}

public AAAaaa(String name, Integer age, String address, String work, String school, String studentjson, Date createtime) {
this.name = name;
this.age = age;
this.address = address;
this.work = work;
this.school = school;
this.studentjson = studentjson;
this.createtime = createtime;
}

@Override
public String toString() {
return "AAAaaa{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", work='" + work + '\'' +
", school='" + school + '\'' +
", studentjson='" + studentjson + '\'' +
", createtime=" + createtime +
'}';
}
}

 

測試類:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestDemo {
public static void main(String[] args) {
AAAaaa aa=new AAAaaa("xiaoming",20,"北京","英語老師","北京小學","[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]",new Date());
System.out.println(aa);
String s = JSONObject.toJSONString(aa);
//測試序列化
System.out.println(s);
//跟AAAaaa這個對象無關,所以跟@JSONField注解無關
System.out.println(JSONObject.parseObject(s));
//測試反序列化
System.out.println(JSONObject.parseObject(s,AAAaaa.class));
}
}

 

測試結果

1
2
3
4
AAAaaa{name='xiaoming', age=20, address='北京', work='英語老師', school='北京小學', studentjson='[{"studentName":"lily","studentAge":12},{"studentName":"lucy","studentAge":15}]', createtime=Tue Sep 03 17:19:12 CST 2019}
{"address":"北京","userAge":20,"userName":"xiaoming","time":"2019-09-03 17:19:12","json":[{"studentName":"lily","studentAge":12},{"studentName":"lucy","studentAge":15}],"userSchool":"北京小學"}
{"time":"2019-09-03 17:19:12","json":[{"studentName":"lily","studentAge":12},{"studentName":"lucy","studentAge":15}],"address":"北京","userSchool":"北京小學","userName":"xiaoming","userAge":20}
AAAaaa{name='xiaoming', age=null, address='null', work='null', school='null', studentjson='[{"studentName":"lily","studentAge":12},{"studentName":"lucy","studentAge":15}]', createtime=Tue Sep 03 17:19:12 CST 2019}

 

1.2@JSONField注解詳細講解

1)ordinal
這個值的設置,可以使對象的屬性按這個順序來輸出,默認值是0,要是都不設置,那就按屬性名稱的字母順序來輸出(數字小的或字母在前的先輸出)
2)name
直接把原來的屬性名稱代碼,給替換成別名
3)format
這個針對日期屬性,至於他的值,你可以隨意設置格式化格式,前提是復合那個SimpleDateFormat這個類的格式化時間的格式就好,估計是通用的
4)serialize
序列化,默認值是true,都是序列化的,我在model里面設置了個false,然后可以看到,在輸出json字符串中,這個屬性對應的key和value都不見啦。就是這么個作用
5)deserialize
這個反序列化,默認值也是true,默認都是需要反序列化的,我對name屬性設置是false,在字符串轉對象對時候,發現對象對name屬性是null啦。就是這么個作用。
6)jsonDirect
這個說是,如果對象對某個屬性的值是json字符串的話,就不要在做處理啦,直接就是json。

@JSONField注解可以作用在Field字段上也可以作用在setter和getter方法上,當作用在setter方法上時,就相當於根據name到json中尋找對應的值,並調用該setter對象賦值。當作用在getter上時,在bean轉換為json時,其key值為name定義的值。

2.@JSONType

@JSONType(naming = PropertyNamingStrategy.PascalCase) 大駝峰命名
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)

可以多個屬性並列放@JSONType(orders = {“name”,”work”,”address”},includes={“name”,”work”,”address”})

1
2
3
@JSONType(orders = {"z","a","b","c","d"})    相當於ordinal 
@JSONType(includes={"name","work","address"})  相當於serialize(參與序列化的有name,work,address)
@JSONType(ignores={"name","work","address"})   不參與序列化的有name,work,address

 

3.SerializeFilter

3.1SerializeFilter屬性使用

1)在代碼中使用

1
2
3
4
5
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd"; //把AAAaaa類中format = "yyyy-MM-dd HH:mm:ss"去掉
AAAaaa aa = new AAAaaa(null, 20, "北京", "英語老師", "北京小學", "[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]", new Date());
String s = JSONObject.toJSONString(aa, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteMapNullValue);
//測試序列化
System.out.println(s);

 

測試結果

1
{"address":"北京","userAge":20,"userName":null,"time":"2019-09-04","json":[{"studentName":"lily","studentAge":12},{"studentName":"lucy","studentAge":15}],"userSchool":"北京小學"}

 

2)在@JSONField注解中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AAAaaa {

@JSONType(serialzeFeatures = {SerializerFeature.WriteNullStringAsEmpty,SerializerFeature.WriteMapNullValue})
private String name;
private Integer age;
private String address;
private String work;
private String school;
private String studentjson;
private Date createtime;

......
}

 

3)在@JSONType注解中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
@JSONType(serialzeFeatures = {SerializerFeature.WriteNullStringAsEmpty,SerializerFeature.WriteMapNullValue})
public class AAAaaa {

private String name;
private Integer age;
private String address;
private String work;
private String school;
private String studentjson;
private Date createtime;

......
}

 

3.2SerializeFilter屬性列表

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package com.alibaba.fastjson.serializer;

public enum SerializerFeature {
QuoteFieldNames,//輸出key時是否使用雙引號,默認為true
/**
*
*/
UseSingleQuotes,//使用單引號而不是雙引號,默認為false
/**
*
*/
WriteMapNullValue,//是否輸出值為null的字段,默認為false
/**
* 1.目前版本的fastjon默認對enum對象使用WriteEnumUsingName屬性,因此會將enum值序列化為其Name。
* 2.使用WriteEnumUsingToString方法可以序列化時將Enum轉換為toString()的返回值;
* 同時override toString函數能夠將enum值輸出需要的形式。但是這樣做會帶來一個問題,對應的反序列化使用的Enum的靜態方法
* valueof可能無法識別自行生成的toString(),導致反序列化出錯。
* 3.如果將節省enum序列化后的大小,可以將enum序列化其ordinal值,保存為int類型。
* fastJson在反序列化時,如果值為int,則能夠使用ordinal值匹配,找到合適的對象。
* fastjson要將enum序列化為ordinal只需要禁止WriteEnumUsingName feature。
* 首先根據默認的features排除WriteEnumUsingName,然后使用新的features序列化即可。
* int features=SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false)
* JSON.toJSONString(obj,features,SerializerFeature.EMPTY);
*/
WriteEnumUsingToString,//用枚舉toString()值輸出

WriteEnumUsingName,//用枚舉name()輸出
/**
*
*/
UseISO8601DateFormat,//Date使用ISO8601格式輸出,默認為false
/**
*
*/
WriteNullListAsEmpty,//List字段如果為null,輸出為[],而非null,默認為false
/**
*
*/
WriteNullStringAsEmpty,//字符類型字段如果為null,輸出為"",而非null,默認為false
/**
*
*/
WriteNullNumberAsZero,//數值字段如果為null,輸出為0,而非null(包括Integer類型,如果為null,輸出為0),默認為false
/**
*
*/
WriteNullBooleanAsFalse,//Boolean字段如果為null,輸出為false,而非null,默認為false
/**
*
*/
SkipTransientField,//如果是true,類中的Get方法對應的Field是transient,序列化時將會被忽略。默認為true
/**
*
*/
SortField,//按字段名稱排序后輸出。默認為false
/**
*
*/

/** @deprecated棄用 */
@Deprecated
WriteTabAsSpecial,//把\t做轉義輸出,默認為false
/**
*
*/
PrettyFormat,//結果是否格式化,默認為false
/**
*
*/
WriteClassName,//序列化時寫入類型信息,默認為false。反序列化是需用到
/**
* 對於值相同的鍵,不使用引用表達
* 不使用類似於下面的方式來輸出:
* {"$ref":"$"} 引用根對象
* {"$ref":"@"} 引用自己
* {"$ref":".."} 引用父對象
* {"$ref":"../.."} 引用父對象的父對象
* {"$ref":"$.members[0].reportTo"} 基於路徑的引用
*/
DisableCircularReferenceDetect,//消除對同一對象循環引用的問題,默認為false
/**
*
*/
WriteSlashAsSpecial,//對斜杠'/'進行轉義
/**
*
*/
BrowserCompatible,//將中文都會序列化為\uXXXX格式,字節數會多一些,但是能兼容IE 6,默認為false
/**
*
*/
WriteDateUseDateFormat,//全局修改日期格式,默認為false,格式為yyyy-MM-dd HH:mm:ss
/**
*
*/
NotWriteRootClassName,
/**
*
*/

/** @deprecated */
DisableCheckSpecialChar,//一個對象的字符串屬性中如果有特殊字符如雙引號,將會在轉成json時帶有反斜杠轉移符。如果不需要轉義,可以使用這個屬性。默認為false
/**
* 按["field1",field2,field3,"field4","field5","field6"]這樣的格式來輸出bean
*/
BeanToArray,//將對象轉為array輸出
/**
*
*/
WriteNonStringKeyAsString,//把所有的鍵都作為String
/**
*
*/
NotWriteDefaultValue,
/**
*
*/
BrowserSecure,
/**
*
*/
IgnoreNonFieldGetter,//忽略沒有getter的字段
/**
*
*/
WriteNonStringValueAsString,
/**
*
*/
IgnoreErrorGetter,
/**
*
*/
WriteBigDecimalAsPlain,
/**
*
*/
MapSortField;
/**
*
*/

public final int mask = 1 << this.ordinal();
public static final SerializerFeature[] EMPTY = new SerializerFeature[0];
public static final int WRITE_MAP_NULL_FEATURES = WriteMapNullValue.getMask() | WriteNullBooleanAsFalse.getMask() | WriteNullListAsEmpty.getMask() | WriteNullNumberAsZero.getMask() | WriteNullStringAsEmpty.getMask();

private SerializerFeature() {
}

public final int getMask() {
return this.mask;
}

/**
* 判斷features所代表的特性集合中是否包含有feature特性
* 這里巧妙的使用了一個掩碼(mask)來計算,mask是通過對1進行移位得到的
* 因為每一個SerializerFeature在枚舉中的序數是固定的,所以mask的
* 值就是像下面的二進制形式:
* 00000000000000000000000000000001
* 00000000000000000000000000000010
* 00000000000000000000000000000100
* 00000000000000000000000000001000
* ......
* 10000000000000000000000000000000
* 所以通過&運算很容易就判斷出features中有沒有feature。例如:
* feature是WriteMapNullValue(0000000000000000000000000000100),
* features是15(0000000000000000000000000001111),很容易知道features
* 中包含有feature。(可通過SerializerFeature數組計算features,下面提供的
* of方法就可以計算features的值(SerializerFeature數組的掩碼(mask)))
* @param features
* @param feature
* @return
*/
public static boolean isEnabled(int features, SerializerFeature feature) {
return (features & feature.mask) != 0;
}

/**
* 檢查features或者fieaturesB是否包含feature
* 和上一個方法一樣
* @param features
* @param fieaturesB
* @param feature
* @return
*/
public static boolean isEnabled(int features, int fieaturesB, SerializerFeature feature) {
int mask = feature.mask;
return (features & mask) != 0 || (fieaturesB & mask) != 0;
}

/**
* 為features增加feature特性,或者剔除feature特性
* 當state為true時為features增加feature特性
* 當state為false時為features剔除feature特性
* @param features
* @param feature
* @param state
* @return
*/
public static int config(int features, SerializerFeature feature, boolean state) {
if(state) {
features |= feature.mask;
} else {
features &= ~feature.mask;
}

return features;
}

/**
* 計算SerializerFeature數組的掩碼(mask)
* 通過|運算把features中的特性疊加起來
* @param features
* @return
*/
public static int of(SerializerFeature[] features) {
if(features == null) {
return 0;
} else {
int value = 0;
SerializerFeature[] var2 = features;
int var3 = features.length;

for(int var4 = 0; var4 < var3; ++var4) {
SerializerFeature feature = var2[var4];
value |= feature.mask;
}

return value;
}
}
}

相關博客鏈接: https://blog.csdn.net/liupeifeng3514/article/details/79166566


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM