jackson使用入門

jackson是java中最常用的json處理工具包之一,其他類似功能的包括gson和fastjson等。本文將簡單介紹jackson的基礎(chǔ)知識(shí),以作為各位讀者未來使用的參考。

三種使用方式

jackson有三種處理json的方式,分別為

  • data binding
  • tree model
  • streaming api

data binding

這種方式可以在json字符串和pojo對(duì)象之間直接進(jìn)行轉(zhuǎn)換。比如說我們有一個(gè)json字符串

{"firstName":"dizzy","lastName":"dwarf"}

通過這種方式我們可以直接將其轉(zhuǎn)換成一個(gè)Person類的實(shí)例,其中firstName和lastName是Person類定義的兩個(gè)成員變量。

ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.readValue(jsonStr, Person.class);

tree model

這種方式類似于xml的DOM解析,在json字符串和DOM樹之間進(jìn)行轉(zhuǎn)換,DOM樹的節(jié)點(diǎn)是JsonNode類型。其優(yōu)點(diǎn)在于以統(tǒng)一的方式看待json字符串中的各個(gè)部分,使用起來更靈活。

ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(jsonStr);
JsonNode firstName = root.path("firstName");

構(gòu)建DOM樹

如何構(gòu)建JsonNode的DOM樹呢?JsonNode是抽象類,需要使用ObjectNodeArrayNode等子類。

ObjectNode objectNode = objectMapper.createObjectNode();
ArrayNode arrayNode = objectMapper.createArrayNode();

streaming api

這種方式類似于xml的SAX解析,每次處理一個(gè)事件,或者這里叫token更合適。

streaming api反序列化

反序列化用的是JsonParser,它的使用方式和迭代器非常相似。你每次處理的都是一個(gè)token,比如說在上面這個(gè)json字符串中,包括{、firstName、dizzy、lastName、dwarf、}等6個(gè)token,通過調(diào)用nextToken方法可以獲得下一個(gè)token。

streaming api序列化

序列化用的JsonGenerator,它的方法都非常直觀,比如說writeStartObject、writeStringField、writeEndObject等,這里就不具體介紹了。

注解

通過注解可以定制jackson的各種特性,這里只介紹最常用的幾個(gè)。

序列化注解

  • @JsonGetter
    注解在方法上,將方法返回的值作為字段序列化的值
public class Person {
    private String firstName;

    @JsonGetter("firstName")
    public String getFirstName() {
        return firstName + "_modified";
    }
    // 省略了setter方法
}

這樣一個(gè)firstName為"dizzy"的Person序列化后就變成了

{"firstName":"dizzy_modified"}
  • @JsonSerialize
    注解在成員變量上,使用指定的JsonSerializer實(shí)現(xiàn)類來序列化這個(gè)字段,這個(gè)實(shí)現(xiàn)類最關(guān)鍵的是serialize方法,這個(gè)方法會(huì)為你提供JsonGenerator對(duì)象作為參數(shù),讓你可以通過它來構(gòu)建序列化后的值。
  • @JsonValue
    注解在方法上,將方法返回的值作為整個(gè)對(duì)象序列化的結(jié)果。

反序列化注解

  • @JsonSetter
    @JsonGetter的逆過程
  • @JsonDeserialize
    @JsonSerialize的逆過程
  • @JsonAlias
    默認(rèn)情況下java對(duì)象中的成員變量名和json字符串的字段名是一對(duì)一關(guān)系的,但是可能存在這樣一種情況。比如firstName這個(gè)成員變量,可能json字符串有不同的來源,有的地方這個(gè)字段叫firstName,另外一些地方傳的字段名稱是fName。這個(gè)時(shí)候就可以用@JsonAlias使這個(gè)成員變量接受更多的名稱。

通用注解

  • @JsonProperty
    指定該成員變量對(duì)應(yīng)的json字符串的字段名,默認(rèn)情況下如果兩者相同的話不需要使用該注解。
  • @JsonIgnore
    指定該成員變量不參與序列化和反序列化

具體問題解決

下劃線和駝峰轉(zhuǎn)換

一般情況下java變量命名采用駝峰方式,而json字符串可能采用下劃線方式。解決方式為在類或者成員變量上增加以下注解

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

需要注意的是雖然反序列化的時(shí)候first_name會(huì)對(duì)應(yīng)到firstName變量,但是序列化的時(shí)候也會(huì)輸出為first_name

多態(tài)處理

有時(shí)候我們希望根據(jù)json字符串中某個(gè)字段的取值反序列化成不同的子類,比如說type為1是Student,type為2是Teacher,注意Student和Teacher必須繼承同一個(gè)父類Person。

@JsonTypeInfo(use = JsonTypeInfo.ID.NAME, property = "type", defaultImpl = Person.class)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Student.class, name = "1"),
    @JsonSubTypes.Type(value = Teacher.class, name = "2")
})
public class Person {}
  • property是決定子類型的字段名稱
  • defaultImpl是默認(rèn)情況下反序列化的類型,這里指的是當(dāng)type不為1和2時(shí)
  • name是子類型對(duì)應(yīng)的字段取值

帶泛型參數(shù)的List和Map的反序列化

如果我們希望ObjectMapper.readValue返回List<Person>或者M(jìn)ap<String, Person>,由于List<Person>.class和Map<String, Person>.class在java中是不合法的,需要借助于TypeReference

TypeReference<List<Person>> typeReference = new TypeReference<List<Person>>(){};
List<Person> list = objectMapper.readValue(jsonStr, typeReference);

jackson如何集成Spring

Spring提供的MappingJackson2MessageConverter類封裝了ObjectMapper,如果希望對(duì)ObjectMapper進(jìn)行定制,可以自己生成一個(gè)MappingJackson2MessageConverter對(duì)象并注冊(cè)為bean

只對(duì)部分成員變量序列化同時(shí)不影響反序列化

有時(shí)候我們希望只對(duì)部分成員變量進(jìn)行序列化,如果用@JsonIgnore,會(huì)同時(shí)影響反序列化。這個(gè)時(shí)候我們可以用@JsonView注解指定某個(gè)視圖類的序列化結(jié)果包含該成員變量。

更多參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,658評(píng)論 1 32
  • 概要 64學(xué)時(shí) 3.5學(xué)分 章節(jié)安排 電子商務(wù)網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,851評(píng)論 0 3
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 14,314評(píng)論 0 15
  • 孤星明月漸遠(yuǎn)去, 旭日朝霞方東升。 何來烈火欲燒天, 原是彤云正蔽空。
    無衣客閱讀 330評(píng)論 2 1
  • 鄉(xiāng)關(guān)才近便聞雞,不是江南舊柳堤。 夏暑因山秋更早,夜涼與月句為宜。 臨街靜靜無車擾,隔巷深深有鳥啼。 詩興久違今又...
    雁閣秋容閱讀 572評(píng)論 5 12

友情鏈接更多精彩內(nèi)容