jackson是java中最常用的json處理工具包之一淆珊,其他類似功能的包括gson和fastjson等。本文將簡單介紹jackson的基礎知識浴讯,以作為各位讀者未來使用的參考司倚。
三種使用方式
jackson有三種處理json的方式,分別為
- data binding
- tree model
- streaming api
data binding
這種方式可以在json字符串和pojo對象之間直接進行轉換灼伤。比如說我們有一個json字符串
{"firstName":"dizzy","lastName":"dwarf"}
通過這種方式我們可以直接將其轉換成一個Person類的實例,其中firstName和lastName是Person類定義的兩個成員變量咪鲜。
ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.readValue(jsonStr, Person.class);
tree model
這種方式類似于xml的DOM解析狐赡,在json字符串和DOM樹之間進行轉換,DOM樹的節(jié)點是JsonNode
類型疟丙。其優(yōu)點在于以統(tǒng)一的方式看待json字符串中的各個部分颖侄,使用起來更靈活。
ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(jsonStr);
JsonNode firstName = root.path("firstName");
構建DOM樹
如何構建JsonNode
的DOM樹呢享郊?JsonNode
是抽象類览祖,需要使用ObjectNode
和ArrayNode
等子類。
ObjectNode objectNode = objectMapper.createObjectNode();
ArrayNode arrayNode = objectMapper.createArrayNode();
streaming api
這種方式類似于xml的SAX解析炊琉,每次處理一個事件展蒂,或者這里叫token更合適。
streaming api反序列化
反序列化用的是JsonParser
苔咪,它的使用方式和迭代器非常相似锰悼。你每次處理的都是一個token,比如說在上面這個json字符串中团赏,包括{箕般、firstName、dizzy舔清、lastName隘世、dwarf、}等6個token鸠踪,通過調用nextToken
方法可以獲得下一個token丙者。
streaming api序列化
序列化用的JsonGenerator
,它的方法都非常直觀营密,比如說writeStartObject
械媒、writeStringField
、writeEndObject
等,這里就不具體介紹了纷捞。
注解
通過注解可以定制jackson的各種特性痢虹,這里只介紹最常用的幾個。
序列化注解
-
@JsonGetter
注解在方法上主儡,將方法返回的值作為字段序列化的值
public class Person {
private String firstName;
@JsonGetter("firstName")
public String getFirstName() {
return firstName + "_modified";
}
// 省略了setter方法
}
這樣一個firstName為"dizzy"的Person序列化后就變成了
{"firstName":"dizzy_modified"}
-
@JsonSerialize
注解在成員變量上奖唯,使用指定的JsonSerializer
實現(xiàn)類來序列化這個字段,這個實現(xiàn)類最關鍵的是serialize
方法糜值,這個方法會為你提供JsonGenerator
對象作為參數(shù)丰捷,讓你可以通過它來構建序列化后的值。 -
@JsonValue
注解在方法上寂汇,將方法返回的值作為整個對象序列化的結果病往。
反序列化注解
-
@JsonSetter
@JsonGetter
的逆過程 -
@JsonDeserialize
@JsonSerialize
的逆過程 -
@JsonAlias
默認情況下java對象中的成員變量名和json字符串的字段名是一對一關系的,但是可能存在這樣一種情況骄瓣。比如firstName這個成員變量停巷,可能json字符串有不同的來源,有的地方這個字段叫firstName榕栏,另外一些地方傳的字段名稱是fName畔勤。這個時候就可以用@JsonAlias
使這個成員變量接受更多的名稱。
通用注解
-
@JsonProperty
指定該成員變量對應的json字符串的字段名扒磁,默認情況下如果兩者相同的話不需要使用該注解庆揪。 -
@JsonIgnore
指定該成員變量不參與序列化和反序列化
具體問題解決
下劃線和駝峰轉換
一般情況下java變量命名采用駝峰方式,而json字符串可能采用下劃線方式渗磅。解決方式為在類或者成員變量上增加以下注解
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
需要注意的是雖然反序列化的時候first_name會對應到firstName變量,但是序列化的時候也會輸出為first_name
多態(tài)處理
有時候我們希望根據(jù)json字符串中某個字段的取值反序列化成不同的子類检访,比如說type為1是Student始鱼,type為2是Teacher,注意Student和Teacher必須繼承同一個父類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是默認情況下反序列化的類型医清,這里指的是當type不為1和2時
- name是子類型對應的字段取值
帶泛型參數(shù)的List和Map的反序列化
如果我們希望ObjectMapper.readValue返回List<Person>或者Map<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
会烙,如果希望對ObjectMapper
進行定制,可以自己生成一個MappingJackson2MessageConverter
對象并注冊為bean
只對部分成員變量序列化同時不影響反序列化
有時候我們希望只對部分成員變量進行序列化筒捺,如果用@JsonIgnore
柏腻,會同時影響反序列化。這個時候我們可以用@JsonView
注解指定某個視圖類的序列化結果包含該成員變量系吭。