javascript
JSON最佳实践
JSON是一種文本方式展示結構化數據的方式,從產生的時候開始就由于其簡單好用、跨平臺,特別適合HTTP下數據的傳輸(例如現在很流行的REST)而被廣泛使用。by?kimmking@163.com
1、JSON是什么
JSON起源于1999年的JS語言規范ECMA262的一個子集(即15.12章節描述了格式與解析),后來2003年作為一個數據格式ECMA404(很囧的序號有不有?)發布。
2006年,作為rfc4627發布,這時規范增加到18頁,去掉沒用的部分,十頁不到。
JSON的應用很廣泛,這里有超過100種語言下的JSON庫:json.org。
更多的可以參考這里,關于json的一切。
2、優缺點、標準與schema
2.1 結構與類型
這估計是最簡單標準規范之一:
- 只有兩種結構:對象內的鍵值對集合結構和數組,對象用{}表示、內部是”key”:”value”,數組用[]表示,不同值用逗號分開
- 基本數值有7個: false / null / true / object / array / number / string
- 再加上結構可以嵌套,進而可以用來表達復雜的數據
- 一個簡單實例:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | {"Image": {"Width": 800,"Height": 600,"Title": "View from 15th Floor","Thumbnail": {"Url": "http://www.example.com/image/481989943","Height": 125,"Width": "100"},"IDs": [116, 943, 234, 38793]} } |
2.2 優點
- 基于純文本,所以對于人類閱讀是很友好的。
- 規范簡單,所以容易處理,開箱即用,特別是JS類的ECMA腳本里是內建支持的,可以直接作為對象使用。
- 平臺無關性,因為類型和結構都是平臺無關的,而且好處理,容易實現不同語言的處理類庫,可以作為多個不同異構系統之間的數據傳輸格式協議,特別是在HTTP/REST下的數據格式。
2.3 缺點
缺點也很明顯:
- 性能一般,文本表示的數據一般來說比二進制大得多,在數據傳輸上和解析處理上都要更影響性能。
- 缺乏schema,跟同是文本數據格式的XML比,在類型的嚴格性和豐富性上要差很多。XML可以借由XSD或DTD來定義復雜的格式,并由此來驗證XML文檔是否符合格式要求,甚至進一步的,可以基于XSD來生成具體語言的操作代碼,例如apache xmlbeans。并且這些工具組合到一起,形成一套龐大的生態,例如基于XML可以實現SOAP和WSDL,一系列的ws-*規范。但是我們也可以看到JSON在缺乏規范的情況下,實際上有更大一些的靈活性,特別是近年來REST的快速發展,已經有一些schema相關的發展(例如理解JSON Schema,使用JSON Schema,?在線schema測試),也有類似于WSDL的WADL出現。
3. 常用技術與工具
3.1 相關技術以及與XML的關系
- 使用JSON實現RPC(類似XML-RPC):JSON-RPC
- 使用JSON實現path查詢操作(類似XML-PATH):JsonPATH
- 在線查詢工具:JsonPATH
例如上面的示例json,用表達式$.Image.IDs[:1]查詢,得到116:
image
我們看到JSON與XML是如此之像,實際上這兩個格式可以看做一個是學院排,一個是平民派。一個對象從POJO轉換成XML與JSON的過程,基本是一致的(絕大部分工作可以復用,以后有機會再詳細聊這個過程),10年前我自己也做過一個基于XML的RPC(http://code.google.com/p/rpcfx/,貌似已經被墻),里面實現了java和dotnet、JS的XML序列化與反序列化,同時作為一個副產品,實現了JSON序列化。
后來thoughtsworks公司出品的XStream就是同時做了XML與JSON的序列化。而創建Jackson庫的組織本來叫fasterxml,就是處理xml的。當然從這個角度來看,Fastjson庫,稍微改改也是一個高性能的XML序列化庫。
只是XML有著更嚴格的結構,更豐富的工具生態,拿查詢與操作來說,XML還有XQuery、XLST等工具。處理方式上也有DOM方式與SAX流模式,這兩個絕然不同的技術。
單從性能來考慮,XML更是有VTD-XML這種解決了DOM消耗太大內存與SAX只能單向每個節點讀一次不能隨機讀的缺點的高性能處理方式。
3.2 Java類庫
- Fastjson
- Jackson
- Gson
- Xstream
3.3 工具
- 格式化工具:jsbeautifier
- chrome插件:5個Json View插件
- 在線Mock:?在線mock
- 其他Mock:SoapUI可以支持,SwaggerUI也可以,RestMock也可以。
image
image
4. JSON編碼指南
4.1 Google JSON風格指南
遵循好的設計與編碼風格,能提前解決80%的問題:
- 英文版Google JSON Style Guide:https://google.github.io/styleguide/jsoncstyleguide.xml
- 中文版Google JSON風格指南:https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md
簡單摘錄如下:
- 屬性名和值都是用雙引號,不要把注釋寫到對象里面,對象數據要簡潔
- 不要隨意結構化分組對象,推薦是用扁平化方式,層次不要太復雜
- 命名方式要有意義,比如單復數表示
- 駝峰式命名,遵循Bean規范
- 使用版本來控制變更沖突
- 對于一些關鍵字,不要拿來做key
- 如果一個屬性是可選的或者包含空值或null值,考慮從JSON中去掉該屬性,除非它的存在有很強的語義原因
- 序列化枚舉類型時,使用name而不是value
- 日期要用標準格式處理
- 設計好通用的分頁參數
- 設計好異常處理
4.2 使用JSON實現API
JSON API與Google JSON風格指南有很多可以相互參照之處。
JSON API是數據交互規范,用以定義客戶端如何獲取與修改資源,以及服務器如何響應對應請求。
JSON API設計用來最小化請求的數量,以及客戶端與服務器間傳輸的數據量。在高效實現的同時,無需犧牲可讀性、靈活性和可發現性。
5. REST
todo list
- dubbox
- resteasy
- restlet
- jersey
image
6. SwaggerUI實現API文檔管理與在線測試
todo list
image
7. JSON使用場景分析
JSON的使用,依據不同用途,有幾個典型的場景:
- 此時可以使用類似Dubbox之類的框架,或者原始一些SpringMVC的Controller上直接@ResponseBody或@RestController也可以。
- 強烈建議在Dubbox之類的rest之上再加一個Nginx轉發,這樣一些策略的控制,比如同源的控制、簡單的緩存策略、安全策略等都可以放到Nginx上來做,也利于多個機器時的負載均衡。
- 建議使用swaggerUI來自動實現API文檔和在線測試。功能很強大,操作簡單,而且可以mock接口,在后臺沒有做好之前,前臺就可以先開發了。
- 可以使用RestUnit或SoapUI來實現自動化測試與壓力測試。
基本同上,可以參考Google JSON風格指南與JSON API章節。
8.JSON的一些經驗
最近在協助處理一些Fastjson的bug問題,發現最常見的其實是大家使用的不規范性,這樣碰到各種坑的可能性就很大。根據我平時使用的經驗,以及總結大家常見的問題,歸納如下:
8.1 遵循Java Beans規范與JSON規范
實踐告訴我們:遵循beans規范和JSON規范的方式,能減少大部分的問題,比如正確實現setter、getter,用別名就加annotation。注意基本類型的匹配轉換,比如在fastjson的issue見到試圖把”{“a”:{}}”中的a轉換成List的。
8.2 使用正常的key
盡量不要使用數字等字符開頭的key,盡量使用符合Java的class或property命名規范的key,這樣會減少不必要的沖突。在jsonpath或js里,a.1可能會被解釋成a[1]或a[“1”],這些都會帶來不必要的麻煩。
8.3 關于日期處理
這一點前面的Google JSON風格指南里也提到了,盡量使用標準的日期格式。或者序列化和反序列化里都是用同樣的datePattern格式。
8.4 自定義序列化與反序列化
對于新手來說,自定義序列化是一切罪惡的根源。
盡量不要使用自定義序列化,除非萬不得已,優先考慮使用注解過濾,別名等方式,甚至是重新建一個VO類來組裝實際需要的屬性。使用自定義序列化時一切要小心,因為這樣會導致兩個問題:
- 改變了pojo <-> jsonstring 的自然對應關系,從而不利于閱讀代碼和排查問題,你改變的關系無法簡單的從bean和json上看出來了;
- 反序列化可能出錯,因為對應不上原來的屬性了。
如果只是序列化發出去(響應)的是JSON數據、傳過來(請求)的數據格式跟JSON無關或者是標準的,此時自定義序列化就無所謂了,反正是要接收方來處理。
8.5 JSONObject的使用
JSONObject是JSON字符串與pojo對象轉換過程中的中間表達類型,實現了Map接口,可以看做是一個模擬JSON對象鍵值對再加上多層嵌套的數據集合,對象的每一個基本類型屬性是map里的一個key-value,一個非基本類型屬性是一個嵌套的JSONObject對象(key是屬性名稱,value是表示這個屬性值的對象的JSONObject)。如果以前用過apache beanutils里的DynamicBean之類的,就知道JSONObject也是一種動態描述Bean的實現,相當于是拆解了Bean本身的結構與數據。這時候由于JSONObject里可能會沒有記錄全部的Bean類型數據,例如泛型的具體子類型之類的元數據,如果JSONObject與正常的POJO混用,出現問題的概率較高。
下列方式盡量不要使用:
| 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 | public class TestBean{@Setter @Getterprivate TestBean1 testBean1;@Setter @Getterprivate JSONObject testBean2; // 盡量不要在POJO里用JSONObject }``` 應該從設計上改為都用POJO比較合適:```java public class TestBean{@Setter @Getterprivate TestBean1 testBean1;@Setter @Getterprivate TestBean2 testBean2;; // 使用POJO }``` 相對的,寫一些臨時性的測試代碼,demo代碼,可以直接全部用JSONObject先快速run起來。同理,jsonstring中嵌套jsonstring也盡量不要用,例如:```javascript {"name":"zhangsan","score":"{\"math\":78,\"history\":82}" } |
應該改為全部都是JSON風格的結構:
| 1 2 3 4 5 6 7 | {"name":"zhangsan","score":{"math":78,"history":82} } |
另外,對于jsonstring轉POJO(或POJO轉jsonstring),盡量使用直接轉的方式,而不是先轉成JSONObject過渡的方式。特別是對于Fastjson,由于性能優化的考慮,這兩個執行的代碼是不一樣的,可能導致不一樣的結果。
| 1 2 3 4 5 6 7 8 9 | String jsonstring = "{\"a\":12}";// 不推薦這種方式 // 除非這里需要對jsonObject做一些簡單處理 JSONObject jsonObject = JSON.parseObject(jsonstring); A a = jsonObject.toJavaObject(A.class);// 推薦方式 A a = JSON.parseObject(jsonstring, A.class); |
8.6 Hibernate相關問題
懶加載與級聯,可能導致出現問題,例如hibernate,建議封裝一層VO類型來序列化。使用VO類還有一個好處,就是可以去掉一些沒用的屬性,減少數據量,同時可以加上額外的屬性。
8.7 深層嵌套與泛型問題
盡量不要在使用過多的層次嵌套的同時使用泛型(List、Map等),可能導致類型丟失,而且問題比較難查。
8.8 抽象類型與子類型問題
盡量不要在同一個Bean的層次結構里使用多個子類型對象,可能導致類型丟失,而且問題比較難查。當然我們可以通過代碼顯示的傳遞各種正確的類型,但是這樣做引入了更多的不確定性。良好的做法應該是一開始設計時就避免出現這些問題。
8.9 避免循環引用
盡量避免循環引用,這個雖然可以通過序列化特性禁掉,但是如果能避免則避免。
8.10 注意編碼和不可見字符
對于InputStream、OutputStream的處理,有時候會報一些奇怪的錯誤,not match之類的,這時候也許我們看日志里的json字符串可能很正常,但就是出錯。
這時可能就是編碼的問題了,可能是導致字符錯亂,也可能是因為UTF-8文件的BOM頭,這些潛在的問題可能在二進制數據轉文本的時候,因為一些不可見字符無法顯示,導致日志看起來只有正常字符而是正確的,問題很難排查。
處理辦法就是按二進制的方式把Stream保存起來,然后按hex方式查看,看看是否有多余字符,或者其他錯誤。
9.fastjson的最佳實踐
9.1 Maven下引入Fastjson
pom.xml文件里添加依賴即可:
| 1 2 3 4 5 | <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.32</version> </dependency> |
9.2 序列化一個對象成JSON字符串
| 1 2 3 4 5 6 7 | User user = new User(); user.setName("校長"); user.setAge(3); user.setSalary(new BigDecimal("123456789.0123")); String jsonString = JSON.toJSONString(user); System.out.println(jsonString); // 輸出 {"age":3,"name":"校長","old":false,"salary":123456789.0123} |
9.3 反序列化一個JSON字符串成Java對象
| 1 2 3 4 5 6 7 8 9 | String jsonString = "{\"age\":3,\"birthdate\":1496738822842,\"name\":\"校長\",\"old\":true,\"salary\":123456789.0123}";User u = JSON.parseObject(jsonString ,User.class);System.out.println(u.getName());// 輸出 校長String jsonStringArray = "[{\"age\":3,\"birthdate\":1496738822842,\"name\":\"校長\",\"old\":true,\"salary\":123456789.0123}]"; List<User> userList = JSON.parseArray(jsonStringArray, User.class); System.out.println(userList.size()); // 輸出 1 |
9.4 日期格式處理
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 | private final static String defaultPatttern = "yyyy-MM-dd HH:mm:ss"; private final static DateTimeFormatter defaultFormatter = DateTimeFormatter.ofPattern(defaultPatttern); private final static DateTimeFormatter formatter_dt19_tw = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); private final static DateTimeFormatter formatter_dt19_cn = DateTimeFormatter.ofPattern("yyyy年M月d日 HH:mm:ss"); private final static DateTimeFormatter formatter_dt19_cn_1 = DateTimeFormatter.ofPattern("yyyy年M月d日 H時m分s秒"); private final static DateTimeFormatter formatter_dt19_kr = DateTimeFormatter.ofPattern("yyyy?M?d? HH:mm:ss"); private final static DateTimeFormatter formatter_dt19_us = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss"); private final static DateTimeFormatter formatter_dt19_eur = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); private final static DateTimeFormatter formatter_dt19_de = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); private final static DateTimeFormatter formatter_dt19_in = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");private final static DateTimeFormatter formatter_d8 = DateTimeFormatter.ofPattern("yyyyMMdd"); private final static DateTimeFormatter formatter_d10_tw = DateTimeFormatter.ofPattern("yyyy/MM/dd"); private final static DateTimeFormatter formatter_d10_cn = DateTimeFormatter.ofPattern("yyyy年M月d日"); private final static DateTimeFormatter formatter_d10_kr = DateTimeFormatter.ofPattern("yyyy?M?d?"); private final static DateTimeFormatter formatter_d10_us = DateTimeFormatter.ofPattern("MM/dd/yyyy"); private final static DateTimeFormatter formatter_d10_eur = DateTimeFormatter.ofPattern("dd/MM/yyyy"); private final static DateTimeFormatter formatter_d10_de = DateTimeFormatter.ofPattern("dd.MM.yyyy"); private final static DateTimeFormatter formatter_d10_in = DateTimeFormatter.ofPattern("dd-MM-yyyy");private final static DateTimeFormatter ISO_FIXED_FORMAT =DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());private final static String formatter_iso8601_pattern = "yyyy-MM-dd'T'HH:mm:ss"; private final static DateTimeFormatter formatter_iso8601 = DateTimeFormatter.ofPattern(formatter_iso8601_pattern); |
默認序列化Date輸出使用”yyyy-MM-dd HH:mm:ss”格式,可以用UseISO8601DateFormat特性換成”yyyy-MM-dd’T’HH:mm:ss”格式。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | JSON.defaultTimeZone = TimeZone.getTimeZone("Asia/Shanghai"); JSON.defaultLocale = Locale.US;public static class Model {@JSONField(format = "MMM dd, yyyy h:mm:ss aa")private java.util.Date date;public java.util.Date getDate() {return date;}public void setDate(java.util.Date date) {this.date = date;}@JSONField(format = "MMM-dd-yyyy h:mm:ss aa")public java.sql.Date date2; } |
9.5 常見序列化特性的使用
Fastjson的序列化特性定義在枚舉類com\alibaba\fastjson\serializer\SerializerFeature.java中,目前正好有30項。
可以通過設置多個特性到FastjsonConfig中全局使用,也可以在某個具體的JSON.writeJSONString時作為參數使用。
使用示例如下(可以參見此處):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Word word = new Word(); word.setA("a"); word.setB(2); word.setC(true); word.setD("d"); word.setE(""); word.setF(null); word.setDate(new Date());System.out.println(JSON.toJSONString(word)); System.out.println(JSON.toJSONString(word, SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty,SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteNullListAsEmpty)); |
9.6 Annotation注解的使用
1) JSONField
可以配置在屬性(setter、getter)和字段(必須是public field)上。
詳情參見此處:JSONField用法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.alibaba.fastjson.annotation;public @interface JSONField {// 配置序列化和反序列化的順序,1.1.42版本之后才支持int ordinal() default 0;// 指定字段的名稱String name() default "";// 指定字段的格式,對日期格式有用String format() default "";// 是否序列化boolean serialize() default true;// 是否反序列化boolean deserialize() default true; } |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @JSONField(name="ID") public int getId() {return id;}// 配置date序列化和反序列使用yyyyMMdd日期格式 @JSONField(format="yyyyMMdd") public Date date1; // 不序列化@JSONField(serialize=false)public Date date2;// 不反序列化@JSONField(deserialize=false)public Date date3;// 按ordinal排序@JSONField(ordinal = 2)private int f1;@JSONField(ordinal = 1)private int f2; |
2) JSONType
- 自定義序列化:ObjectSerializer
- 子類型處理:SeeAlso
- JSONType.alphabetic屬性: fastjson缺省時會使用字母序序列化,如果你是希望按照java fields/getters的自然順序序列化,可以配置JSONType.alphabetic,使用方法如下:
| 1 2 3 4 5 6 | @JSONType(alphabetic = false) public static class B {public int f2;public int f1;public int f0; } |
9.7 自定義序列化與反序列化
- 自定義序列化
只需要2步:參見此處
1)實現ObjectSerializer
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class CharacterSerializer implements ObjectSerializer {public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {SerializeWriter out = serializer.out;Character value = (Character) object;if (value == null) {out.writeString("");return;}char c = value.charValue();if (c == 0) {out.writeString("\u0000");} else {out.writeString(value.toString());}} } |
2)注冊ObjectSerializer
| 1 | SerializeConfig.getGlobalInstance().put(Character.class, new CharacterSerializer()); |
- 自定義反序列化
只需要2步:參見此處
1)自定義實現ObjectDeserializer
| 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 | public static enum OrderActionEnum {FAIL(1), SUCC(0);private int code;OrderActionEnum(int code){this.code = code;} }public static class Msg {public OrderActionEnum actionEnum;public String body; }public static class OrderActionEnumDeser implements ObjectDeserializer {@SuppressWarnings("unchecked")@Overridepublic <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {Integer intValue = parser.parseObject(int.class);if (intValue == 1) {return (T) OrderActionEnum.FAIL;} else if (intValue == 0) {return (T) OrderActionEnum.SUCC;}throw new IllegalStateException();}@Overridepublic int getFastMatchToken() {return JSONToken.LITERAL_INT;}} |
2)注冊并使用ObjectDeserializer
| 1 2 3 4 5 6 7 8 9 10 11 12 | ParserConfig.getGlobalInstance().putDeserializer(OrderActionEnum.class, new OrderActionEnumDeser());{Msg msg = JSON.parseObject("{\"actionEnum\":1,\"body\":\"A\"}", Msg.class);Assert.assertEquals(msg.body, "A");Assert.assertEquals(msg.actionEnum, OrderActionEnum.FAIL); } {Msg msg = JSON.parseObject("{\"actionEnum\":0,\"body\":\"B\"}", Msg.class);Assert.assertEquals(msg.body, "B");Assert.assertEquals(msg.actionEnum, OrderActionEnum.SUCC); } |
9.8 自定義序列化之過濾器
- 全局的過濾器:JSON.toJSONString方法的參數中可以配置處理所有類型的SerializeFilter
- 類級別過濾器:Class_Level_SerializeFilter
- 屬性過濾器:使用PropertyPreFilter過濾屬性
- 多余字段處理器:ExtraProcessor 用于處理多余的字段、
ExtraTypeProvider用于處理多余字段時提供類型信息 - 定制反序列化:在fastjson-1.2.9版本后提供了ExtraProcessable接口,用于定制對象的反序列化功能,可用于添加沒有的字段
- 標簽過濾:JSONField(label),相當于分組
- 自動識別嵌套對象子類型:FieldTypeResolver
9.9 與Spring MVC的配合使用
FastJson 提供了Spring MVC HttpMessageConverter的實現,將POJO輸出為JSONP,支持跨域數據訪問。
FastJsonpHttpMessageConverter4 for Spring MVC 4.2+:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <mvc:annotation-driven><mvc:message-converters><beanclass="com.alibaba.fastjson.support.spring.FastJsonpHttpMessageConverter4"><property name="supportedMediaTypes"><list><value>application/json;charset=UTF-8</value></list></property></bean></mvc:message-converters> </mvc:annotation-driven><mvc:default-servlet-handler /><bean id="fastJsonpResponseBodyAdvice" class="com.alibaba.fastjson.support.spring.FastJsonpResponseBodyAdvice"><constructor-arg><list><value>callback</value><value>jsonp</value></list></constructor-arg> </bean> |
詳細配置參見此處
9.10 與Spring Boot的集成使用
參見此處:spring-boot-starter-fastjson
9.11 泛型處理
在fastjson中提供了一個用于處理泛型反序列化的類TypeReferenceeReference
9.12jaxrs支持
FastJson 提供了JAX-RS Provider的實現?FastJsonProvider
可用于在構建Restful服務時使用FastJson進行數據的Serialize and Deserialize
9.13 swagger支持
增加對swagger的支持
dubbox與swagger的集成
9.14 默認參數配置
1)序列化
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public static int DEFAULT_GENERATE_FEATURE;static {int features = 0;features |= SerializerFeature.QuoteFieldNames.getMask(); // key用引號引起來features |= SerializerFeature.SkipTransientField.getMask(); // 忽略transientfeatures |= SerializerFeature.WriteEnumUsingName.getMask(); // enum輸出namefeatures |= SerializerFeature.SortField.getMask(); ? ? ? ? ?// 字段排序{String featuresProperty = IOUtils.getStringProperty("fastjson.serializerFeatures.MapSortField");int mask = SerializerFeature.MapSortField.getMask();if ("true".equals(featuresProperty)) {features |= mask;} else if ("false".equals(featuresProperty)) {features &= ~mask;}}DEFAULT_GENERATE_FEATURE = features;} |
2)反序列化
| 1 2 3 4 5 6 7 8 9 10 11 12 | static {int features = 0;features |= Feature.AutoCloseSource.getMask();//檢查json格式features |= Feature.InternFieldNames.getMask();//features |= Feature.UseBigDecimal.getMask(); //數值使用BigDecimalfeatures |= Feature.AllowUnQuotedFieldNames.getMask();//支持key不用引號引起來features |= Feature.AllowSingleQuotes.getMask();//支持單引號features |= Feature.AllowArbitraryCommas.getMask();//支持連續多個逗號features |= Feature.SortFeidFastMatch.getMask();//排序后快速匹配features |= Feature.IgnoreNotMatch.getMask();//忽略不匹配的屬性和字段DEFAULT_PARSER_FEATURE = features;} |
更多功能 todo list
10.Fastjson的設計說明
todo list
from:?http://kimmking.github.io/2017/06/06/json-best-practice/
總結
- 上一篇: JDK1.8 十大新特性详解
- 下一篇: Spring MVC【入门】就这一篇