Location:Action,新的JSON序列化的思路

一般來講,序列化json,實際上有2總方式 java

  • 經過當前流行的JSON工具。
  • 編寫代碼,手工序列化

這倆種方式各有優劣。第一種方式毫無疑問,不須要開發者作什麼工做,直接調用序列化接口,輸出就是json。可是,若是須要特殊需求,好比須要將日期格式化按照yyyy-mm-dd 輸出,這些JSON工具能夠指定日期格式化輸出,好比FastJSON裏: git

SerializeConfig mapping = new SerializeConfig();
String dateFormat = "yyyy-MM-dd";  
mapping.put(Date.class, new SimpleDateFormatSerializer(dateFormat));
String json = JSON.toJSONString(obj,mapping);

 在Jackon裏,代碼也是相似,如: 程序員

ObjectMapper objectMapper = new ObjectMapper();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
objectMapper.setDateFormat(sdf);
objectMapper.writeValue(writer, obj);


對於這種常見需求,JSON工具總有經過Annotation&&SerializerFeature組合來解決 ,但也有應對不了的,如一下一些問題
  1. 對象裏有個字段是Calendar,我想格式化yyyy-MM-dd 輸出。
  2. 對象裏另外有個字段也是Calendar,我想僅僅輸出time(Long類型)
  3. 對象及其關聯對象的id我都不想輸出。
  4. 若是某個對象的集合屬性爲null,則僅僅輸出[], 但另一個集合屬性未null,則輸出null。

當前流行工具老是疲於應付這種「變態」序列化需求,不停的升級版本增長處理類來解決這些需求。有沒有終極解決辦法嗎? web

    在回答這個問題前,讓咱們迴歸到我說的第二種序列化解決方法,就是手工編寫代碼。經過硬編碼貌似是是終極奧義。各類變態序列化需求都能經過硬編碼來解決。然而,這種終極奧義的問題是序列化太麻煩了。面對企業應用,互聯網應用中成百上千的模型,手工來序列化是不現實的,那麼,有沒有第三個辦法,既能方便序列化對象,有具備很強的序列化能力,應付各類變態需求呢? 正則表達式

    以我看來,的確有第三個辦法,正如正則表達式那樣,能分析各類複雜文本,依靠的是(位置&指令)*。序列化JSON,實際上也須要相似正則表達式的思路,我抽象爲(locatoin:action)*. location 多是指一個對象的屬性名,也可能泛指某個類型的對象。action 是指序列化操做,好比忽略此location,或者一個排序動做,一個格式化動做,或者,是一個調用此對象的某個方法的動做等等。對於如下User對象,咱們能夠指定一系列的(Location:Action)* json

public class User{  
    String name="joel";
    int age =12;    
    double salary=12.32266;
    Date bir = new Date();
    Customer  customer = new Customer();
    List<Customer>  list = new ArrayList<Customer>();
    List<Customer>  deleteList = null;
    //getter and setter     方法必須有,在此忽略
}


Location:Action  描述
name:i
name 指的是User對象的name屬性,i表明一個操做,意思ignore。表示此字段不須要序列化
~d:f/yyyy-MM-dd/
~d 表示全部日期類型(包含其子類),動做是調用一個格式化函數f,參數是yyyy-MM-dd
bir:$.getTime
bir是User對象bir屬性,輸出時調用其getTime方法輸出毫秒時間
~*::O/name, age/
將User類的name,age放到前面優先顯示
~*:Ci/name,id/
若是User實例被引用過(循環引用),則僅僅輸出id,和name。即避免了循環引用問題,也同時有明確的輸出
deleteList :?null->[]
deleteList是User的屬性,若是爲null,則輸出[]

如上幾個簡單例子能夠看到基於(Location:Action)序列化功能的強大和靈活,甚至能夠 組合Action,好比 app

~L/java.util.Calendar*/:$.getTime->f/yyyy-MM-dd/,能夠解釋爲對於全部對象類型爲java.util.Calendar及其子類,輸出的時候,先調用$.getTime,得到Date,而後再格式化輸出。 函數

因而可知,若是定義好Location,以及提供必定數量的Action,和內置一些表達式操做(如?empty->dosomething),便具備超過傳統的基於(Annotation&&SerializerFeature)的JSON工具的序列化能力。不只僅如此,經過指定好policy,policy=(location:action)*,能夠實現對同一對象的不一樣序列化策略。好比代碼: 工具

String json = JsonTool.serialize(User,"id:i"); //不輸出id
//or  指定一個序列化策略,age,name先輸出,適合有特殊需求的對象或者沒法註解(第三方)對象
String json2 = JsonTool.serialize(User,"~*:O/age,name/"));


因而可知,序列化JSON的第三種道路,即"(Location:Action)*" 很是接近我認爲的序列化JSON終極奧義,他具備當前流行"(Annotation&SerializerFeature)*" 操做簡便性,也具備硬編碼序列化的的靈活性。我寫了一個beetl-json 做爲驗證,斷斷續續花了2周時間和犧牲了週末:),自我感受效果不錯的,我貼一些Beetl-JSON 代碼能夠看看 性能

JsonTool.addLocationAction("~d","f/yyyy.MM.dd/");   
JsonTool.addLocationAction("~L/java.util.Calendar*/","$.getTime->f/yyyy-MM-dd/");
//類json格式的策略,用逗號分開多個locationAction
JsonTool.addPolicy("~f:f/#.##/,~c:?null->[]");
// 默認是緊湊輸出,使用true,將換行和縮進  
JsonTool.pretty = true;
//序列化User
String json = JsonTool.serialize(User);
//or  指定一個序列化策略,age,name先輸出,適合有特殊需求的對象或者沒法註解(第三方)對象
String json2 = JsonTool.serialize(User,"~*:O/age,name/"));


User對象定義以下:

@Json(
    policys={
            @JsonPolicy(location="name", action="nn/newUserName/"),
            @JsonPolicy(location="deleteList", action="?empty->[]")                     
    }
)
public class User{  
    String name="joel";
    int age =12;    
    double salary=12.32266;
    Customer  customer = new Customer();
    List<Customer>  list = new ArrayList<Customer>();
    List<Customer>  deleteList = null;
    //getter and setter     方法必須有,在此忽略
}


    序列化性能如今還未徹底考慮中,由於只作了2周,功能還不全,還屬於驗證階段,此時若是比較性能,比較佔便宜,我把我初步的性能測試代碼放到 performance test 裏了,包含了FastJSON,Jackson.在我老式筆記本里,單線程序列化一個普通對象1百萬次,性能以下:

初步性能測試仍是不錯的。beetl-json略快一些,只須要1.238秒,不過考慮到beetl-json如今功能還未全,且對日期輸出作了優化,而FastJson沒有作。因此這三個之間,實際沒有太大的性能差距。

  在當今web應用,互聯網應用火爆的年代,Json序列化是這些應用須要的一種基礎技術能力,基於(Location:Action)* 的JSON工具,相比於傳統(Annotation&SerializerFeature )* 的工具會更加靈活和功能強大,能高度知足程序員的序列化需求。beetl-json會進一步實踐這種思想。讓天下沒有難以序列化的對象

相關文章
相關標籤/搜索