成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Jackson之 Java JSON 解析器

開發 前端
在當今的編程世界里,JSON 已經成為將信息從客戶端傳輸到服務器端的首選協議,可以好不夸張的說,XML 就是那個被拍死在沙灘上的前浪。

 

在當今的編程世界里,JSON 已經成為將信息從客戶端傳輸到服務器端的首選協議,可以好不夸張的說,XML 就是那個被拍死在沙灘上的前浪。

很不幸的是,JDK 沒有 JSON 庫,不知道為什么不搞一下。Log4j 的時候,為了競爭,還推出了 java.util.logging,雖然最后也沒多少人用。

Java 之所以牛逼,很大的功勞在于它的生態非常完備,JDK 沒有 JSON 庫,第三方類庫有啊,還挺不錯,比如說本篇的豬腳——Jackson,GitHub 上標星 6.1k,Spring Boot 的默認 JSON 解析器。

怎么證明這一點呢?

當我們通過 starter 新建一個 Spring Boot 的 Web 項目后,就可以在 Maven 的依賴項中看到 Jackson 的身影。

Jackson 有很多優點:

  • 解析大文件的速度比較快;
  • 運行時占用的內存比較少,性能更佳;
  • API 很靈活,容易進行擴展和定制。

Jackson 的核心模塊由三部分組成:

  • jackson-core,核心包,提供基于“流模式”解析的相關 API,包括 JsonPaser 和 JsonGenerator。
  • jackson-annotations,注解包,提供標準的注解功能;
  • jackson-databind ,數據綁定包,提供基于“對象綁定”解析的相關 API ( ObjectMapper ) 和基于“樹模型”解析的相關 API (JsonNode)。

01、引入 Jackson 依賴

要想使用 Jackson,需要在 pom.xml 文件中添加 Jackson 的依賴。

  1. <dependency> 
  2.     <groupId>com.fasterxml.jackson.core</groupId> 
  3.     <artifactId>jackson-databind</artifactId> 
  4.     <version>2.10.1</version> 
  5. </dependency> 

jackson-databind 依賴于 jackson-core 和 jackson-annotations,所以添加完 jackson-databind 之后,Maven 會自動將 jackson-core 和 jackson-annotations 引入到項目當中。

Maven 之所以討人喜歡的一點就在這,能偷偷摸摸地幫我們把該做的做了。

02、使用 ObjectMapper

Jackson 最常用的 API 就是基于”對象綁定” 的 ObjectMapper,它通過 writeValue 的系列方法將 Java 對象序列化為 JSON,并且可以存儲成不同的格式。

  • writeValueAsString(Object value) 方法,將對象存儲成字符串
  • writeValueAsBytes(Object value) 方法,將對象存儲成字節數組
  • writeValue(File resultFile, Object value) 方法,將對象存儲成文件

來看一下存儲成字符串的代碼示例:

  1. import com.fasterxml.jackson.core.JsonProcessingException; 
  2. import com.fasterxml.jackson.databind.ObjectMapper; 
  3.  
  4. /** 
  5.  * 微信搜索「沉默王二」,回復 Java 
  6.  * 
  7.  * @author 沉默王二 
  8.  * @date 2020/11/26 
  9.  */ 
  10. public class Demo { 
  11.     public static void main(String[] args) throws JsonProcessingException { 
  12.         Writer wanger = new Writer("沉默王二", 18); 
  13.         ObjectMapper mapper = new ObjectMapper(); 
  14.         String jsonString = mapper.writerWithDefaultPrettyPrinter() 
  15.                 .writeValueAsString(wanger); 
  16.         System.out.println(jsonString); 
  17.     } 
  18.  
  19. class Writer { 
  20.     private String name
  21.     private int age; 
  22.  
  23.     public Writer(String nameint age) { 
  24.         this.name = name
  25.         this.age = age; 
  26.     } 
  27.  
  28.     public String getName() { 
  29.         return name
  30.     } 
  31.  
  32.     public void setName(String name) { 
  33.         this.name = name
  34.     } 
  35.  
  36.     public int getAge() { 
  37.         return age; 
  38.     } 
  39.  
  40.     public void setAge(int age) { 
  41.         this.age = age; 
  42.     } 

程序輸出結果如下所示:

  1.   "name" : "沉默王二"
  2.   "age" : 18 

不是所有的字段都支持序列化和反序列化,需要符合以下規則:

  • 如果字段的修飾符是 public,則該字段可序列化和反序列化(不是標準寫法)。
  • 如果字段的修飾符不是 public,但是它的 getter 方法和 setter 方法是 public,則該字段可序列化和反序列化。getter 方法用于序列化,setter 方法用于反序列化。
  • 如果字段只有 public 的 setter 方法,而無 public 的 getter 方 法,則該字段只能用于反序列化。

如果想更改默認的序列化和反序列化規則,需要調用 ObjectMapper 的setVisibility() 方法。否則將會拋出 InvalidDefinitionException 異常。

ObjectMapper 通過 readValue 的系列方法從不同的數據源將 JSON 反序列化為 Java 對象。

  • readValue(String content, Class valueType) 方法,將字符串反序列化為 Java 對象
  • readValue(byte[] src, Class valueType) 方法,將字節數組反序列化為 Java 對象
  • readValue(File src, Class valueType) 方法,將文件反序列化為 Java 對象

來看一下將字符串反序列化為 Java 對象的代碼示例:

  1. import com.fasterxml.jackson.core.JsonProcessingException; 
  2. import com.fasterxml.jackson.databind.ObjectMapper; 
  3.  
  4. public class Demo { 
  5.     public static void main(String[] args) throws JsonProcessingException { 
  6.         ObjectMapper mapper = new ObjectMapper(); 
  7.         String jsonString = "{\n" + 
  8.                 "  \"name\" : \"沉默王二\",\n" + 
  9.                 "  \"age\" : 18\n" + 
  10.                 "}"
  11.         Writer deserializedWriter = mapper.readValue(jsonString, Writer.class); 
  12.         System.out.println(deserializedWriter); 
  13.     } 
  14.  
  15. class Writer{ 
  16.     private String name
  17.     private int age; 
  18.  
  19.     // getter/setter 
  20.  
  21.     @Override 
  22.     public String toString() { 
  23.         return "Writer{" + 
  24.                 "name='" + name + '\'' + 
  25.                 ", age=" + age + 
  26.                 '}'
  27.     } 

程序輸出結果如下所示:

  1. Writer{name='沉默王二', age=18} 

PS:如果反序列化的對象有帶參的構造方法,它必須有一個空的默認構造方法,否則將會拋出 InvalidDefinitionException 一行。

  1. Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.itwanger.jackson.Writer` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) 
  2.  at [Source: (String)"{ 
  3.   "name" : "沉默王二"
  4.   "age" : 18 
  5. }"; line: 2, column: 3] 
  6.  at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) 
  7.  at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589) 
  8.  at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1055) 
  9.  at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) 
  10.  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) 
  11.  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) 
  12.  at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202) 
  13.  at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205) 
  14.  at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173) 
  15.  at com.itwanger.jackson.Demo.main(Demo.java:19) 

Jackson 最常用的 API 就是基于”對象綁定” 的 ObjectMapper,

ObjectMapper 也可以將 JSON 解析為基于“樹模型”的 JsonNode 對象,來看下面的示例。

  1. import com.fasterxml.jackson.core.JsonProcessingException; 
  2. import com.fasterxml.jackson.databind.JsonNode; 
  3. import com.fasterxml.jackson.databind.ObjectMapper; 
  4.  
  5. public class JsonNodeDemo { 
  6.     public static void main(String[] args) throws JsonProcessingException { 
  7.         ObjectMapper mapper = new ObjectMapper(); 
  8.         String json = "{ \"name\" : \"沉默王二\", \"age\" : 18 }"
  9.         JsonNode jsonNode = mapper.readTree(json); 
  10.         String name = jsonNode.get("name").asText(); 
  11.         System.out.println(name); // 沉默王二 
  12.     } 

借助 TypeReference 可以將 JSON 字符串數組轉成泛型 List,來看下面的示例:

  1. import com.fasterxml.jackson.core.JsonProcessingException; 
  2. import com.fasterxml.jackson.core.type.TypeReference; 
  3. import com.fasterxml.jackson.databind.ObjectMapper; 
  4.  
  5. import java.util.List; 
  6.  
  7. public class TypeReferenceDemo { 
  8.     public static void main(String[] args) throws JsonProcessingException { 
  9.         ObjectMapper mapper = new ObjectMapper(); 
  10.         String json = "[{ \"name\" : \"沉默王三\", \"age\" : 18 }, { \"name\" : \"沉默王二\", \"age\" : 19 }]"
  11.         List<Author> listAuthor = mapper.readValue(json, new TypeReference<List<Author>>(){}); 
  12.         System.out.println(listAuthor); 
  13.     } 
  14. class Author{ 
  15.     private String name
  16.     private int age; 
  17.  
  18.     // getter/setter 
  19.  
  20.     // toString 

03、更高級的配置

Jackson 之所以牛掰的一個很重要的因素是可以實現高度靈活的自定義配置。

在實際的應用場景中,JSON 中常常會有一些 Java 對象中沒有的字段,這時候,如果直接解析的話,會拋出 UnrecognizedPropertyException 異常。

下面是一串 JSON 字符串:

  1. String jsonString = "{\n" + 
  2.                 "  \"name\" : \"沉默王二\",\n" + 
  3.                 "  \"age\" : 18\n" + 
  4.                 "  \"sex\" : \"男\",\n" + 
  5.                 "}"

但 Java 對象 Writer 中沒有定義 sex 字段:

  1. class Writer{ 
  2.     private String name
  3.     private int age; 
  4.  
  5.     // getter/setter 

我們來嘗試解析一下:

  1. ObjectMapper mapper = new ObjectMapper(); 
  2. Writer deserializedWriter = mapper.readValue(jsonString, Writer.class); 

不出意外,拋出異常了,sex 無法識別。

  1. Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "sex" (class com.itwanger.jackson.Writer), not marked as ignorable (2 known properties: "name""age"]) 
  2.  at [Source: (String)"{ 
  3.   "name" : "沉默王二"
  4.   "age" : 18, 
  5.   "sex" : "男" 
  6. }"; line: 4, column: 12] (through reference chain: com.itwanger.jackson.Writer["sex"]) 

怎么辦呢?可以通過 configure() 方法忽略掉這些“無法識別”的字段。

  1. mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

除此之外,還有其他一些有用的配置信息,來了解一下:

  1. // 在序列化時忽略值為 null 的屬性 
  2. mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
  3. // 忽略值為默認值的屬性 
  4. mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT); 

04、處理日期格式

對于日期類型的字段,比如說 java.util.Date,如果不指定格式,序列化后將顯示為 long 類型的數據,這種默認格式的可讀性很差。

  1.   "age" : 18, 
  2.   "birthday" : 1606358621209 

怎么辦呢?

第一種方案,在 getter 上使用 @JsonFormat 注解。

  1. private Date birthday; 
  2.  
  3. // GMT+8 是指格林尼治的標準時間,在加上八個小時表示你現在所在時區的時間 
  4. @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss"
  5. public Date getBirthday() { 
  6.     return birthday; 
  7.  
  8. public void setBirthday(Date birthday) { 
  9.     this.birthday = birthday; 

再來看一下結果:

  1.   "age" : 18, 
  2.   "birthday" : "2020-11-26 03:02:30" 

具體代碼如下所示:

  1. ObjectMapper mapper = new ObjectMapper(); 
  2. Writer wanger = new Writer("沉默王二", 18); 
  3. wanger.setBirthday(new Date()); 
  4. String jsonString = mapper.writerWithDefaultPrettyPrinter() 
  5.                 .writeValueAsString(wanger); 
  6. System.out.println(jsonString); 

第二種方案,調用 ObjectMapper 的 setDateFormat() 方法。

  1. ObjectMapper mapper = new ObjectMapper(); 
  2. mapper.setDateFormat(StdDateFormat.getDateTimeInstance()); 
  3. Writer wanger = new Writer("沉默王二", 18); 
  4. wanger.setBirthday(new Date()); 
  5. String jsonString = mapper.writerWithDefaultPrettyPrinter() 
  6.                 .writeValueAsString(wanger); 
  7. System.out.println(jsonString); 

輸出結果如下所示:

  1.   "name" : "沉默王二"
  2.   "age" : 18, 
  3.   "birthday" : "2020年11月26日 上午11:09:51" 

05、字段過濾

在將 Java 對象序列化為 JSON 時,可能有些字段需要過濾,不顯示在 JSON 中,Jackson 有一種比較簡單的實現方式。

@JsonIgnore 用于過濾單個字段。

  1. @JsonIgnore 
  2. public String getName() { 
  3.     return name

@JsonIgnoreProperties 用于過濾多個字段。

  1. @JsonIgnoreProperties(value = { "age","birthday" }) 
  2. class Writer{ 
  3.     private String name
  4.     private int age; 
  5.     private Date birthday; 

06、自定義序列化和反序列化

當 Jackson 默認序列化和反序列化不能滿足實際的開發需要時,可以自定義新的序列化和反序列化類。

自定義的序列化類需要繼承 StdSerializer,同時重寫 serialize() 方法,利用 JsonGenerator 生成 JSON,示例如下:

  1. public class CustomSerializer extends StdSerializer<Man> { 
  2.     protected CustomSerializer(Class<Man> t) { 
  3.         super(t); 
  4.     } 
  5.  
  6.     public CustomSerializer() { 
  7.         this(null); 
  8.     } 
  9.  
  10.     @Override 
  11.     public void serialize(Man value, JsonGenerator gen, SerializerProvider provider) throws IOException { 
  12.         gen.writeStartObject(); 
  13.         gen.writeStringField("name", value.getName()); 
  14.         gen.writeEndObject(); 
  15.     } 
  16.  
  17. class Man{ 
  18.     private int age; 
  19.     private String name
  20.  
  21.     public Man(int age, String name) { 
  22.         this.age = age; 
  23.         this.name = name
  24.     } 
  25.  
  26.     public int getAge() { 
  27.         return age; 
  28.     } 
  29.  
  30.     public void setAge(int age) { 
  31.         this.age = age; 
  32.     } 
  33.  
  34.     public String getName() { 
  35.         return name
  36.     } 
  37.  
  38.     public void setName(String name) { 
  39.         this.name = name
  40.     } 

定義好自定義序列化類后,要想在程序中調用它們,需要將其注冊到 ObjectMapper 的 Module 中,示例如下所示:

  1. ObjectMapper mapper = new ObjectMapper(); 
  2. SimpleModule module = 
  3.         new SimpleModule("CustomSerializer", new Version(1, 0, 0, nullnullnull)); 
  4. module.addSerializer(Man.class, new CustomSerializer()); 
  5. mapper.registerModule(module); 
  6. Man man = new Man( 18,"沉默王二"); 
  7. String json = mapper.writeValueAsString(man); 
  8. System.out.println(json); 

程序輸出結果如下所示:

  1. {"name":"沉默王二"

自定義序列化類 CustomSerializer 中沒有添加 age 字段,所以只輸出了 name 字段。

再來看一下自定義的反序列化類,繼承 StdDeserializer,同時重寫 deserialize() 方法,利用 JsonGenerator 讀取 JSON,示例如下:

  1. public class CustomDeserializer extends StdDeserializer<Woman> { 
  2.     protected CustomDeserializer(Class<?> vc) { 
  3.         super(vc); 
  4.     } 
  5.  
  6.     public CustomDeserializer() { 
  7.         this(null); 
  8.     } 
  9.  
  10.     @Override 
  11.     public Woman deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
  12.         JsonNode node = p.getCodec().readTree(p); 
  13.         Woman woman = new Woman(); 
  14.         int age = (Integer) ((IntNode) node.get("age")).numberValue(); 
  15.         String name = node.get("name").asText(); 
  16.         woman.setAge(age); 
  17.         woman.setName(name); 
  18.         return woman; 
  19.     } 
  20. class Woman{ 
  21.     private int age; 
  22.     private String name
  23.  
  24.     public Woman() { 
  25.     } 
  26.  
  27.     // getter/setter 
  28.  
  29.     @Override 
  30.     public String toString() { 
  31.         return "Woman{" + 
  32.                 "age=" + age + 
  33.                 ", name='" + name + '\'' + 
  34.                 '}'
  35.     } 

通過 JsonNode 把 JSON 讀取到一個樹形結構中,然后通過 JsonNode 的 get 方法將對應字段讀取出來,然后生成新的 Java 對象,并返回。

定義好自定義反序列化類后,要想在程序中調用它們,同樣需要將其注冊到 ObjectMapper 的 Module 中,示例如下所示:

  1. ObjectMapper mapper = new ObjectMapper(); 
  2. SimpleModule module = 
  3.         new SimpleModule("CustomDeserializer", new Version(1, 0, 0, nullnullnull)); 
  4. module.addDeserializer(Woman.class, new CustomDeserializer()); 
  5. mapper.registerModule(module); 
  6. String json = "{ \"name\" : \"三妹\", \"age\" : 18 }"
  7. Woman woman = mapper.readValue(json, Woman.class); 
  8. System.out.println(woman); 

程序輸出結果如下所示:

  1. Woman{age=18, name='三妹'

07、結語

哎呀,好像不錯哦,Jackson 絕對配得上“最牛掰”這三個字。如果只想簡單的序列化和反序列化,使用 ObjectMapper 的 write 和 read 方法即可。

如果還想更進一步的話,就需要對 ObjectMapper 進行一些自定義配置,或者加一些注解,以及直接自定義序列化和反序列化類,更貼近一些 Java 對象。

需要注意的是,對日期格式的字段要多加小心,盡量不要使用默認配置,可讀性很差。

好了,通過這篇文章的系統化介紹,相信讀者朋友們已經完全摸透 Jackson 了,我們下篇文章見。

本文轉載自微信公眾號「沉默王二」,可以通過以下二維碼關注。轉載本文請聯系沉默王二公眾號。

 

責任編輯:武曉燕 來源: 沉默王二
相關推薦

2022-02-14 13:58:32

操作系統JSON格式鴻蒙

2010-01-07 16:37:04

JSON解析器

2010-01-07 17:24:31

JSON 解析器

2009-03-19 09:26:05

RSS解析器MagpieRSS

2022-06-28 08:17:10

JSON性能反射

2023-12-30 13:33:36

Python解析器JSON

2013-07-23 06:39:49

Json字符串到JsoAndroid開發學習Json萬能解析器

2023-02-07 06:55:26

Kafka消費消息

2010-02-22 13:38:50

Python解析器

2010-02-22 16:51:03

Python 解析器

2024-02-22 08:06:45

JSON策略解析器

2021-03-18 10:56:59

SpringMVC參數解析器

2014-05-06 09:27:54

2017-02-14 10:20:43

Java Class解析器

2011-04-22 13:44:34

JacksonJSON

2009-12-14 18:59:27

Ruby解析器

2022-10-20 11:00:52

SQL解析器

2025-06-26 01:10:00

服務定位解析器Spring

2009-06-19 11:42:09

Scala計算器解析

2021-03-26 09:37:12

Java開發代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费久久久久久 | 99re国产| 欧美激情一区二区三区 | a免费视频 | 久久精品网 | 精品日韩一区 | 成人黄色a | 久久综合久 | 精品国产乱码久久久久久88av | 国产精品99久久久久久久久久久久 | 国产精品一区二区三区在线 | 国产亚洲一区二区精品 | 播放一级毛片 | 亚洲欧洲日韩精品 中文字幕 | 日本又色又爽又黄的大片 | 国产精品99久久久久久大便 | 欧美国产精品 | 成人h电影在线观看 | 国产精品久久久99 | 国产成人久久精品一区二区三区 | 亚洲综合久久精品 | 婷婷久久综合 | 亚洲综合色丁香婷婷六月图片 | 日韩欧美三区 | 欧美一级片在线看 | 国产一级片在线播放 | 亚洲精品1区 | 日韩av电影院 | 国产精品一区2区 | 免费看片国产 | 国产亚洲精品综合一区 | www.色综合 | 国产成人精品综合 | 青青久草 | 在线观看视频91 | 欧美国产精品一区二区三区 | 久久精品91久久久久久再现 | 中文字幕亚洲欧美 | xx视频在线观看 | 亚洲 欧美 在线 一区 | 亚洲欧美在线观看 |