- 簡但且方便的JSON解析,以及與Java對象的相互轉(zhuǎn)換。
- 通過注釋(annotations)和配置(settings)可擴展的配置性。
- 超快的基于流的解析性能,以及完整的數(shù)據(jù)綁定。
但許多其他Java的JSON庫僅考慮方便性和配置性,性能反倒不是面向用戶的最重要層面。
那么,為何Java開發(fā)人員不選擇Jackson而放棄其競爭產(chǎn)品呢?
以上功能的簡短列表其實不過是Jackson功能的冰山一角。 的確,這三個常見功能是重要的,但某種程度上也僅是最基本的東西,起碼,JSON處理器應(yīng)被作為值得考慮的工具使用。除此之外,還有很多很多功能應(yīng)該提供,而這也正是Jackson具備的能力。
因此,讓我們來看看7個樣例 -- 吉祥的數(shù)字 -- "殺手锏" --Jackson近年來領(lǐng)先競爭對手的幾點,依據(jù)先后順序介紹(始于1.0版,最新的一個特性是1.6版加入的)。
1.多處理模式,且可很好協(xié)作
從基本開始,有多種方法來使用和生產(chǎn)JSON數(shù)據(jù),盡管多數(shù)JSON包僅提供單一的處理方式,但卻有三種互補的JSON處理方式(詳細解釋見:There are Tree ways...):
- 增量解析及生成(流模式)。高性能,低開銷的順序訪問。這是最低級的處理方法,相當(dāng)于用于處理XML的SAX和StAX API。所有包裝內(nèi)部必須有這樣的分析器,但并非所有都公開。
- 基于樹的數(shù)據(jù)模式(JSON DOM)。 樹是一種描述JSON內(nèi)容的自然的概念模型,因此許多軟件包提供將JSON作為邏輯樹處理的功能。這是一個靈活的模式,可很好適用某類任務(wù),原型處理或即席訪問也相當(dāng)杰出。
- 數(shù)據(jù)綁定(JSON 與POJO相互轉(zhuǎn)換。極為方便,通常較樹狀模式更高的存取效率,也是適于Java開發(fā)人員通用的自然的數(shù)據(jù)綁定方式。常用于大多數(shù)Java REST框架,諸如JAX-RS。
盡管多角度的好處顯而易見,且各自提供最佳的用例,很少有(如果有的話?)其他的Java JSON包提供這些規(guī)范的處理模式。
大多數(shù)只提供一個模式(org.json以樹組織數(shù)據(jù); Gson實現(xiàn)了數(shù)據(jù)綁定)。 Jackson提供所有模式,所有模式完全支持,且最棒的是,它很容易在兩種模式之間轉(zhuǎn)換,混合和適配。 例如,處理非常大的JSON流時,通常始于流解析,而使用數(shù)據(jù)綁定器將子數(shù)據(jù)段綁定到Java對象:這允許處理巨大的文件而沒有過多的內(nèi)存占用,但卻提供 完整便利的數(shù)據(jù)綁定能力。
2. 可使用任何構(gòu)造及工廠方法(不只是默的零參方法)
大多數(shù)數(shù)據(jù)(對JSON和XML)綁定工具需要一個定義和無參數(shù)的構(gòu)造函數(shù),實例化Java對象,并通過setter設(shè)置屬性或直接訪問字段。 不幸的是它使人們難以利用用“不可變對象”模式,也不同于正常代碼中的訪問模式。
Jackson thinks that developers deserve ability to specify whatever constructor or factory methods they want for instantiation; just annotate thing you want like so:Jacson認為,開發(fā)者應(yīng)該能夠指定他們想為實例化的任何工廠或構(gòu)造方法,只要你喜歡,注釋即可:
public class MyBean {
private final int value;
@JsonCreator
public MyBean(@JsonProperty("value") int v) {
this.value = v;
}
public int getValue() { return value; }
}
而你可以這樣定義POJO,JSON處理的情況下也無妨。(Jackson處理不可變對象的信息,可見: 博客條目 )
3. 不僅是注解,可以混合式注解!
雖然有很多好處,利用Java注解定義元數(shù)據(jù)(如類型安全、編譯時檢查,消除單獨的XML配置,DTY原則等),但也有缺點:如明顯的是,添加注解須能修改類。 而你通常不能(也不應(yīng)該)修改第三方庫的代碼,至少不只是JSON序列化配置方面。
但是,如果你只可以松散動態(tài)關(guān)聯(lián)注釋,而不是嵌入在代碼中?我認為這是個了不起的想法,不管你對Jackson的混合式注解了解多少:您可以將注釋與目標(biāo)類關(guān)聯(lián)(聲明為代理接口或類的一部分)目標(biāo)類的處理方式如同目標(biāo)類本身聲明的注解一樣。
要了解更多信息,請閱讀“ 使用混合式注解實現(xiàn)重用、解耦 ”。
4. 完全支持泛型類型
現(xiàn)在,泛型是Java開發(fā)的完整組成部分,然而,并非所有的JSON庫支持泛型,甚至在處理非常復(fù)雜的數(shù)據(jù)類型時會出錯。
以下列泛型為例:
public class Wrapper<T> { public T value; } public class ListWrapper<E> extends Wrapper<List<E>> { }
若需反序列化這些類型的數(shù)據(jù),代碼如下:
ListWrapper<Integer> w = objectMapper.readValue("[{\"value\":13},{\"value\":7}]", new TypeReference<ListWrapper<Integer>>() { } );
Jackson在弄清必要的東西及生成期望的值方面有點小麻煩,但卻是支持泛型(或更多)的僅有的Java包。
5. 多態(tài)類型
下面是另一個factoid:繼承和多態(tài)類型可用于面向?qū)ο箝_發(fā)的很好方法,但也是任意實現(xiàn)數(shù)據(jù)綁定功能的系統(tǒng)的PITA。
ORM(如Hibernate)大部分的復(fù)雜性是由于沿繼承層次結(jié)構(gòu)扁平化和非扁平化數(shù)據(jù)功能的需要,同樣適用于像JAXB的數(shù)據(jù)序列化包。這也就難怪,當(dāng)時,只有極少數(shù)的Java包支持多態(tài)類型的JSON反序列化,大多數(shù)需要用戶建立應(yīng)用代碼顯式進行類型解析。
杰克遜怎么樣? Jackson 不僅支持自動序列化和反序列化動態(tài)和多態(tài)類型,它試圖盡力把它做好。具體來說,沒有必要公開Java類名(這是其它JSON包支持多態(tài)的唯一機制)作為類 型信息 - 盡管,人們可以,它是可配置 - 但可以使用邏輯類型名稱(通過注解,或注冊實現(xiàn)配置)。不管采用什么類型的標(biāo)識符,包含的方法也可以配置(這很好,因為極大地簡化了JSON格式)。所有 這一切都與合理的缺省功能,具有上下文適用性(這意味著你也可以定義不同類型的設(shè)置!)。
關(guān)于Jackson如何處理多態(tài),詳見: "Jackson 1.5: 多態(tài)類型處理"。
6. 物化接口 (even less monkey code to write!)
盡管支持多態(tài)類型是強大的功能 -- 但卻存在固有的充足的復(fù)雜性 -- 這里是簡化事情的方式:物化接口(或抽象類)。.
給定接口如下:
public interface Bean { public int getX(); public void setX(int value); }
你可能想跳過這一步“Bean接口實現(xiàn),包含兩倍代碼的類”,而直接處理:
Bean bean = objectMapper.readValue(json, Bean.class);
(不收你200元...呃,書寫10行代碼的猴子 - 注意,那就是,我們可以省略接口中的'setX();Bean先生很聰明,知道一些方法需要注入值)。
只有一行配置,便可實現(xiàn)這神奇的功能(又稱“Bean先生”)。更多關(guān)于物化接口的信息參見“ 物化接口信息“。
.我還沒有找到一個愿寫這些接口實現(xiàn)的編碼人員,因此,如果尋找Jackson的單一功能亮點,那就是它了。
7. 支持父/子引用(一對多,ORM)
經(jīng)過前面的通用功能集,我們總結(jié)的東西更為具體:能夠干凈地處理循環(huán)類型的某些子集,成為父/子鏈接。 這些都是互相緊密耦合的引用,其中兩個對象以層次結(jié)構(gòu)的方式交叉引用,如父/子樹節(jié)點的關(guān)聯(lián), 或更常見的,ORM采用的表間連接(join)的描述。
對引用問題(或更普遍的,循環(huán)引用),JSON沒有處理它們的自然方法。,不像Java對象,沒有標(biāo)識信息可用。
常用的解決方法是只標(biāo)記一個被忽略的引用(Jackson可通過使用@ JsonIgnore注解實現(xiàn)),但其缺點是反序列化時會丟失實際的耦合目標(biāo)。
Jackson 有簡單的基于注解的解決該問題的方案:兩個引用需要一個注解(對“子”連接作@JsonManagedReference注解,對“父”或“返回”連接作 @JsonBackReference注解),并在此基礎(chǔ),Jackson知道要省略反向引用的序列化,但反序列化對象時要恢復(fù)它。此方式適用于典型的 ORM用例。
8. 這是全部嗎,有何異議?
實際上,Jackson的一些特性并未包含在本文中,若如此,請指正!
posted on 2012-09-06 16:47
SIMONE 閱讀(8325)
評論(1) 編輯 收藏 所屬分類:
JAVA