Jackson 高級應用

轉自:https://www.ibm.com/developerworks/cn/java/jackson-advanced-application/index.htmlhtml

格式處理(含日期格式)

不一樣類型的日期類型,Jackson 的處理方式也不一樣。java

  • 對於日期類型爲 java.util.Calendar,java.util.GregorianCalendar,java.sql.Date,java.util.Date,java.sql.Timestamp,若不指定格式, 在 json 文件中將序列化 爲 long 類型的數據。顯然這種默認格式,可讀性差,轉換格式是必要的。Jackson 有 不少方式轉換日期格式。
  • 註解方式,請參照" Jackson 的註解的使用"的@ JsonFormat 的示例。
  • ObjectMapper 方式,調用 ObjectMapper 的方法 setDateFormat,將序列化爲指定格式的 string 類型的數據。
  • 對於日期類型爲 java.time.LocalDate,還須要添加代碼 mapper.registerModule(new JavaTimeModule()),同時添加相應的依賴 jar 包

清單 1 . JSR31 0 的配置信息

<dependency> 
<groupId>com.fasterxml.jackson.datatype</groupId> 
<artifactId>jackson-datatype-jsr310</artifactId> 
<version>2.9.1</version> 
</dependency>

對於 Jackson 2.5 如下版本,須要添加代碼 objectMapper.registerModule(new JSR310Module ())node

  • 對於日期類型爲 org.joda.time.DateTime,還須要添加代碼 mapper.registerModule(new JodaModule()),同時添加相應的依賴 jar 包

清單 2. joda 的 配置信息

<dependency> 
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId> 
<version>2.9.1</version> 
</dependency>

泛型反序列化

 

Jackson 對泛型反序列化也提供很好的支持。sql

  • 對於 List 類型 ,能夠調用 constructCollectionType 方法來序列化,也能夠構造 TypeReference 來序列化。

清單 1 . List 泛 型使用示例

CollectionType javaType = mapper.getTypeFactory() 
.constructCollectionType(List.class, Person.class); 
List<Person> personList = mapper.readValue(jsonInString, javaType); 
List<Person> personList = mapper.readValue(jsonInString, new
   TypeReference<List<Person>>(){});

清單 2 . Map 泛型使用示例

//第二參數是 map 的 key 的類型,第三參數是 map 的 value 的類型 
 MapType javaType =
    mapper.getTypeFactory().constructMapType(HashMap.class,String.class,
    Person.class); 
 Map<String, Person> personMap = mapper.readValue(jsonInString,
    javaType); 
 Map<String, Person> personMap = mapper.readValue(jsonInString, new
    TypeReference<Map<String, Person>>() {});

屬性可視化

是 java 對象的全部的屬性都被序列化和反序列化,換言之,不是全部屬性均可視化,默認的屬性可視化的規則以下:json

  • 若該屬性修飾符是 public,該屬性可序列化和反序列化。
  • 若屬性的修飾符不是 public,可是它的 getter 方法和 setter 方法是 public,該屬性可序列化和反序列化。由於 getter 方法用於序列化, 而 setter 方法用於反序列化。
  • 若屬性只有 public 的 setter 方法,而無 public 的 getter 方 法,該屬性只能用於反序列化。

若想更改默認的屬性可視化的規則,須要調用 ObjectMapper 的方法 setVisibility。app

下面的示例使修飾符爲 protected 的屬性 name 也能夠序列化和反序列化。框架

清單 1 . 屬性可視化示例

mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); 
 public class Person { 
public int age; 
 protected String name; 
} 
 PropertyAccessor 支持的類型有 ALL,CREATOR,FIELD,GETTER,IS_GETTER,NONE,SETTER 
 Visibility 支持的類型有 A
    NY,DEFAULT,NON_PRIVATE,NONE,PROTECTED_AND_PUBLIC,PUBLIC_ONLY

屬性過濾

在將 Java 對象序列化爲 json 時 ,有些屬性須要過濾掉,不顯示在 json 中 , Jackson 有多種實現方法。ide

  • 註解方式, 能夠用 @JsonIgnore 過濾單個屬性或用 @JsonIgnoreProperties 過濾多個屬性,示例以下:

清單 1 . 屬性過濾示例一

@JsonIgnore 
public int getAge() 
@JsonIgnoreProperties(value = { "age","birth_date" }) 
public class Person
  • addMixIn 方法加註解方式@JsonIgnoreProperties。

addMixIn 方法簽名以下:spa

public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource);code

addMixIn 方法的做用是用 mixinSource 接口或類的註解會重寫 target 或 target 的子類型的註解。 用ixIn 設置

Person peixIn 的 @JsonIgnoreProperties("name")所重寫,最終忽略的屬性爲 name,最終生成的 json 以下:

{"birthDate":"2017/09/13","age":40}

  • SimpleBeanPropertyFilter 方式。這種方式比前兩種方式更加靈活,也更復雜一些。

首先須要設置@JsonFilter 類或接口,其次設置 addMixIn,將@JsonFilter 做用於 java 對象上,最後調用 SimpleBeanPropertyFilter 的 serializeAllExcept 方法或重寫 S impleBeanPropertyFilter 的 serializeAsField 方法來過濾相關屬性。示例以下:

清單 2 . 屬性過濾示例三

//設置 Filter 類或接口 
 @JsonFilter("myFilter") 
public interface MyFilter {} 
//設置 addMixIn 
mapper.addMixIn(Person.class, MyFilter.class); 
//調用 SimpleBeanPropertyFilter 的 serializeAllExcept 方法 
 SimpleBeanPropertyFilter newFilter = 
 SimpleBeanPropertyFilter.serializeAllExcept("age"); 
//或重寫 SimpleBeanPropertyFilter 的 serializeAsField 方法 
 SimpleBeanPropertyFilter newFilter = new SimpleBeanPropertyFilter() { 
 @Override 
 public void serializeAsField(Object pojo, JsonGenerator jgen, 
 SerializerProvider provider, PropertyWriter writer) 
 throws Exception { 
 if (!writer.getName().equals("age")) { 
 writer.serializeAsField(pojo, jgen, provider); 
 } 
 } 
 }; 
//設置 FilterProvider 
 FilterProvider filterProvider = new SimpleFilterProvider() 
 .addFilter("myFilter", newFilter); 
 mapper.setFilterProvider(filterProvider).writeValueAsString(person);

自定義序列化和反序列化

當 Jackson 默認序列化和反序列化的類不能知足實際須要,能夠自定義新的序列化和反序列化的類。

  • 自定義序列化類。自定義的序列化類須要直接或間接繼承 StdSerializer 或 JsonSerializer,同時須要利用 JsonGenerator 生成 json,重寫方法 serialize,示例以下:

清單 1

public class CustomSerializer extends StdSerializer<Person> { 
@Override 
public void serialize(Person person, JsonGenerator jgen, 
SerializerProvider provider) throws IOException { 
jgen.writeStartObject(); 
jgen.writeNumberField("age", person.getAge()); 
jgen.writeStringField("name", person.getName()); 
jgen.writeEndObject(); 
} 
}

JsonGenerator 有多種 write 方法以支持生成複雜的類型的 json,好比 writeArray,writeTree 等 。若想單首創建 JsonGenerator,能夠經過 JsonFactory() 的 createGenerator。

  • 自定義反序列化類。自定義的反序列化類須要直接或間接繼承 StdDeserializer 或 StdDeserializer,同時須要利用 JsonParser 讀取 json,重寫方法 deserialize,示例以下:

清單 2 . 自定義反序列化

 

public class CustomDeserializer extends StdDeserializer<Person> { 
 @Override 
 public Person deserialize(JsonParser jp, DeserializationContext ctxt) 
 throws IOException, JsonProcessingException { 
 JsonNode node = jp.getCodec().readTree(jp); 
 Person person = new Person(); 
 int age = (Integer) ((IntNode) node.get("age")).numberValue(); 
 String name = node.get("name").asText(); 
 person.setAge(age); 
 person.setName(name); 
return person; 
} 
 }

JsonParser 提供不少方法來讀取 json 信息, 如 isClosed(), nextToken(), getValueAsString()等。若想單首創建 JsonParser,能夠經過 JsonFactory() 的 createParser。

  • 定義好自定義序列化類和自定義反序列化類,若想在程序中調用它們,還須要註冊到 ObjectMapper 的 Module,示例以下:

清單 3 . 注 冊 M odule 示例

SimpleModule module = new SimpleModule("myModule"); 
module.addSerializer(new CustomSerializer(Person.class)); 
module.addDeserializer(Person.class, new CustomDeserializer()); 
mapper.registerModule(module); 
也可經過註解方式加在 java 對象的屬性,方法或類上面來調用它們, 
@JsonSerialize(using = CustomSerializer.class) 
@JsonDeserialize(using = CustomDeserializer.class) 
public class Person

樹模型處理

 

Jackson 也提供了樹模型(tree model)來生成和解析 json。若想修改或訪問 json 部分屬性,樹模型是不錯的選擇。樹模型由 JsonNode 節點組成。程序中經常使用 ObjectNode,ObjectNode 繼承於 JsonNode,示例以下:

清單 1 . ObjectNode 生成和解析 json 示例

ObjectMapper mapper = new ObjectMapper(); 
//構建 ObjectNode 
ObjectNode personNode = mapper.createObjectNode(); 
//添加/更改屬性 
personNode.put("name","Tom"); 
personNode.put("age",40); 
ObjectNode addressNode = mapper.createObjectNode(); 
addressNode.put("zip","000000"); 
addressNode.put("street","Road NanJing"); 
//設置子節點 
personNode.set("address",addressNode); 
//經過 path 查找節點 
JsonNode searchNode = personNode.path("street "); 
//刪除屬性 
((ObjectNode) personNode).remove("address"); 
//讀取 json 
JsonNode rootNode = mapper.readTree(personNode.toString()); 
//JsonNode 轉換成 java 對象 
Person person = mapper.treeToValue(personNode, Person.class); 
//java 對象轉換成 JsonNode 
JsonNode node = mapper.valueToTree(person);

 

總結

本文首先經過與其餘 Java 的 json 的框架比較,介紹了 Jackson 的優勢,而且描述了 Jackson 的 核心模塊的組成,以及每一個部分的做用。而後, 本文經過示例,講解 Jackson 的基本用法,介紹了 ObjectMapper 的 write 和 read 方法,ObjectMapper 的配置信息設定,以及 jackson-annotations 包下注釋的運用。最後,本文詳細的介紹了 Jackson 的高階用法,這也是本文的重點。這些高階用法包括不一樣類型的日期格式處理(普通日期的類型,jdk 8 的日期類型,joda 的日期類型),List 和 Map 等泛型的反序列化,屬性的可視化管理,Jackson 的 三種屬性過濾方式,自定義序列化和反序列化的實現以及樹模型的使用。經過本文的系統地講解,相信讀者對 Jackson 會有更深入而全面的掌握。

相關文章
相關標籤/搜索