URL及日期等特殊資料格式處理-JSON框架Jackson精解第2篇
阿新 • • 發佈:2020-09-20
![](https://img2020.cnblogs.com/other/1815316/202009/1815316-20200920095431256-1928206551.png)
Jackson是Spring Boot預設的JSON資料處理框架,但是其並不依賴於任何的Spring 庫。有的小夥伴以為Jackson只能在Spring框架內使用,其實不是的,沒有這種限制。它提供了很多的JSON資料處理方法、註解,也包括**流式API、樹模型、資料繫結**,以及複雜資料型別轉換等功能。它雖然簡單易用,但絕對不是小玩具,本節為大家介紹Jackson的基礎核心用法,**更多的內容我會寫成一個系列,5-10篇文章,請您繼續關注我。**
* 在 [《序列化與反序列化核心用法-JSON框架Jackson精解第一篇》](http://www.zimug.com/java/spring/%e5%ba%8f%e5%88%97%e5%8c%96%e4%b8%8e%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%e6%a0%b8%e5%bf%83%e7%94%a8%e6%b3%95-json%e6%a1%86%e6%9e%b6jackson%e7%b2%be%e8%a7%a3%e7%ac%ac%e4%b8%80%e7%af%87/.html) 也就是上一篇中,為大家介紹了這些內容
* 一、基礎準備
* 二、序列化方法
* 三、反序列化方法
* 四、欄位重新命名`@JsonProperty`
* 五、忽略null欄位的序列化`@JsonInclude`
* 六、忽略指定的欄位
本篇文章中為大家介紹,一些特殊JOSN資料格式處理-JSON框架Jackson精解第2篇:
* 一、從URL讀取JSON資料
* 二、Unknow Properties 賦值失敗處理
* 三、未賦值Java Bean序列化
* 四、日期格式化
## 一、從URL讀取JSON資料
Jackson不僅可以將字串反序列化為 Java POJO物件,還可以請求遠端的API,獲得遠端服務的JSON響應結果,並將其轉換為Java POJO物件。
~~~
@Test
void testURL() throws IOException {
URL url = new URL("https://jsonplaceholder.typicode.com/posts/1"); //遠端服務URL
ObjectMapper mapper = new ObjectMapper();
//從URL獲取JSON響應資料,並反序列化為java 物件
PostDTO postDTO = mapper.readValue(url, PostDTO.class);
System.out.println(postDTO);
}
~~~
* `jsonplaceholder.typicode.com` 是一個免費提供HTTP測試服務的網站,我們可以利用它進行測試
* 遠端服務API返回結果是一個JSON字串,一篇post稿件包含userId,id,title,content屬性
* PostDTO 是我們自己定義的java 類,同樣包含userId,id,title,content成員變數
下文是控制檯列印輸出結果,postDTO的toString()方法輸出。
~~~
PostDTO(userId=1, id=1, title=sunt aut facere repellat provident occaecati excepturi optio reprehenderit, body=quia et suscipit
suscipit recusandae consequuntur expedita et cum
reprehenderit molestiae ut ut quas totam
nostrum rerum est autem sunt rem eveniet architecto)
~~~
## 二、Unknow Properties 賦值失敗處理
有的時候,客戶端提供的JSON字串屬性,多於我們服務端定義的java 類的成員變數。
![](https://img2020.cnblogs.com/other/1815316/202009/1815316-20200920095431627-1788728165.png)
比如上圖中的兩個類,
* 我們先將PlayerStar序列化為JSON字串,包含age屬性
* 然後將JSON字串轉換為PlayerStar2,不包含age屬性
~~~
@Test
void testUnknowProperties() throws IOException {
ObjectMapper mapper = new ObjectMapper();
PlayerStar player = PlayerStar.getInstance(); //為PlayerStar 各屬性賦值,可以參考本系列文章第一篇
//將PlayerStar序列化為JSON字串
String jsonString = mapper.writeValueAsString(player);
System.out.println(jsonString);
//將JSON字串反序列化為PlayerStar2物件
PlayerStar2 player2 = mapper.readValue(jsonString, PlayerStar2.class);
System.out.println(player2);
}
~~~
當進行反序列化的時候,會丟擲下面的異常。這是因為JSON字串所包含的屬性,多餘Java類的定義(多出一個阿age,賦值時找不到setAge方法)。
~~~
{"age":45,"playerName":"喬丹"}
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "age" (class com.example.demo.javabase.PlayerStar2), not marked as ignorable (one known property: "playerName"])
at [Source: (String)"{"age":45,"playerName":"喬丹"}"; line: 1, column: 10] (through reference chain: com.example.demo.javabase.PlayerStar2["age"])
~~~
如果我們想忽略掉age屬性,不接受我們的java類未定義的成員變數資料,可以使用下面的方法,就不會丟擲UnrecognizedPropertyException了。
~~~
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
~~~
## 三、未賦值Java Bean序列化
有的時候,我們明知道某些類的資料可能為空,我們通常也不會為它賦值。但是客戶端就是需要這個`{}`的JSON物件,我們該怎麼做?
~~~
public class MyEmptyObject {
private Integer i; //沒有get set方法
}
~~~
我們可以為ObjectMapper設定disable序列化特性:FAIL_ON_EMPTY_BEANS,也就是允許物件的所有屬性均未賦值。
~~~
@Test
void testEmpty() throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
String jsonString = mapper.writeValueAsString(new MyEmptyObject());
System.out.println(jsonString);
}
~~~
預設情況下不做設定,會丟擲下面的異常InvalidDefinitionException。設定disable序列化特性:FAIL_ON_EMPTY_BEANS之後,會序列化為`{}`字串。
~~~
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.example.demo.jackson.JacksonTest1$MyEmptyObject and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
~~~
## 四、日期格式化
日期格式化,是我們JSON序列化與反序列化過程中比較常見的需求
~~~
ObjectMapper mapper = new ObjectMapper();
Map temp = new HashMap();
temp.put("now", new Date());
String s = mapper.writeValueAsString(temp);
System.out.println(s);
~~~
預設情況下,針對java中的日期及相關型別,Jackson的序列化結果如下
~~~
{"now":1600564582571}
~~~
如果我們希望在JSON序列化及反序列化過程中,日期格式化,需要做如下的處理
~~~
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); //注意這裡
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd")); //注意這裡
Map temp = new HashMap();
temp.put("now", new Date());
String s = mapper.writeValueAsString(temp);
System.out.println(s);
~~~
控制檯列印輸出結果如下:
~~~
{"now":"2020-09-20"}
~~~
## 歡迎關注我的部落格,裡面有很多精品合集
* 本文轉載註明出處(必須帶連線,不能只轉文字):[字母哥部落格](http://www.zimug.com)。
**覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力!** 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。
* [《手摸手教你學Spring Boot2.0》]( https://www.kancloud.cn/hanxt/springboot2/content )
* [《Spring Security-JWT-OAuth2一本通》](https://www.kancloud.cn/hanxt/springsecurity/content)
* [《實戰前後端分離RBAC許可權管理系統》](https://www.kancloud.cn/hanxt/vue-spring/content)
* [《實戰SpringCloud微服務從青銅到王者》](https://www.kancloud.cn/hanxt/springcloud/content)
* [《VUE深入淺出系列》](https://www.kancloud.cn/hanxt/vuejs2/