淺談JackSon的幾種用法
JackSon介紹
本文使用的JackSon版本為2.9.6。
JackSon是解析JSON和XML的一個框架,優點是簡單易用,效能較高。
JackSon處理JSON的方式
JackSon提供了三種JSON的處理方式。分別是資料繫結,樹模型,流式API。下面會分別介紹這三種方式。
JackSon資料繫結
資料繫結用於JSON轉化,可以將JSON與POJO物件進行轉化。資料繫結有兩種,簡單資料繫結和完整資料繫結。
完整資料繫結
package com.xymxyg.json; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; /** * @author guangsheng.tang * 下面是最常用的場景,將json字串對映為物件,或者是將物件轉化為json字串。這是完整資料繫結。 缺點:這種方法十分方便,但是擴充套件性不強,增加一個欄位便要修改POJO物件,這個操作有一定風險性。並且解析的時候,如果json缺少POJO中的某欄位,映射出的物件對應值預設為null,直接使用有一定風險。如果json物件多了某一欄位,解析過程中會丟擲UnrecognizedPropertyException異常。並且如果json較為複雜的話,POJO物件會顯得特別臃腫。 */ public class CompleteDataBind { public static void main(String[] args) throws IOException { String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\",\"2\"]}"; ObjectMapper mapper = new ObjectMapper(); //Json對映為物件 Student student = mapper.readValue(s,Student.class); //物件轉化為Json String json = mapper.writeValueAsString(student); System.out.println(json); System.out.println(student.toString()); } }
package com.xymxyg.json; /** * @author guangsheng.tang */ public class Student { private int id; private String name; private String sex; private ArrayList<String> array; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public ArrayList<String> getArray() { return array; } public void setArray(ArrayList<String> array) { this.array = array; } @Override public String toString() { return "Student{" + "id=" + id + ",name='" + name + '\'' + ",sex='" + sex + '\'' + ",array=" + Arrays.toString(array.toArray()) + '}'; } }
簡單資料繫結
簡單資料繫結就是將json字串對映為java核心的資料型別。
json型別 | Java型別 |
---|---|
object | LinkedHashMap |
array | ArrayList |
string | String |
number | Integer,Long,Double |
true|false | Boolean |
null | null |
下面演示一個例子,將json轉化為一個Map。通過Map來讀取。
package com.xymxyg.json; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * @author guangsheng.tang * 簡單資料繫結的示例,不用POJO物件,直接對映為一個Map,然後從Map中獲取。 */ public class SimpleDataBind { public static void main(String[] args) throws IOException { Map<String,Object> map = new HashMap<>(16); String s = "{\"id\": 1,\"2\"]," + "\"test\":\"I'm test\",\"base\": {\"major\": \"物聯網\",\"class\": \"3\"}}"; ObjectMapper mapper = new ObjectMapper(); map = mapper.readValue(s,map.getClass()); //獲取id Integer studentId = (Integer) map.get("id"); System.out.println(studentId); //獲取資料 ArrayList list = (ArrayList) map.get("array"); System.out.println(Arrays.toString(list.toArray())); //新增加的欄位可以很方便的處理 String test = (String) map.get("test"); System.out.println(test); //不存在的返回null String notExist = (String) map.get("notExist"); System.out.println(notExist); //巢狀的物件獲取 Map base = (Map) map.get("base"); String major = (String) base.get("major"); System.out.println(major); } }
樹模型
針對JackSon的樹模型結構,我下面寫了一個比較完善的例子。同樣Java樹模型有優點,也有缺點。
package com.xymxyg.json; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; /** * @author guangsheng.tang * JackSon樹模型結構,可以通過get,JsonPointer等進行操作,適合用來獲取大Json中的欄位,比較靈活。缺點是如果需要獲取的內容較多, * 會顯得比較繁瑣。 */ public class TreeModel { public static void main(String[] args) throws IOException { ObjectMapper mapper = new ObjectMapper(); //以下是物件轉化為Json JsonNode root = mapper.createObjectNode(); ((ObjectNode) root).putArray("array"); ArrayNode arrayNode = (ArrayNode) root.get("array"); ((ArrayNode) arrayNode).add("args1"); ((ArrayNode) arrayNode).add("args2"); ((ObjectNode) root).put("name","小紅"); String json = mapper.writeValueAsString(root); System.out.println("使用樹型模型構建的json:"+json); //以下是樹模型的解析Json String s = "{\"id\": 1,\"nullNode\":null,\"class\": \"3\"}}"; //讀取rootNode JsonNode rootNode = mapper.readTree(s); //通過path獲取 System.out.println("通過path獲取值:" + rootNode.path("name").asText()); //通過JsonPointer可以直接按照路徑獲取 JsonPointer pointer = JsonPointer.valueOf("/base/major"); JsonNode node = rootNode.at(pointer); System.out.println("通過at獲取值:" + node.asText()); //通過get可以取對應的value JsonNode classNode = rootNode.get("base"); System.out.println("通過get獲取值:" + classNode.get("major").asText()); //獲取陣列的值 System.out.print("獲取陣列的值:"); JsonNode arrayNode2 = rootNode.get("array"); for (int i = 0; i < arrayNode2.size(); i++) { System.out.print(arrayNode2.get(i).asText()+" "); } System.out.println(); //path和get方法看起來很相似,其實他們的細節不同,get方法取不存在的值的時候,會返回null。而path方法會 //返回一個"missing node",該"missing node"的isMissingNode方法返回值為true,如果呼叫該node的asText方法的話, // 結果是一個空字串。 System.out.println("get方法取不存在的節點,返回null:" + (rootNode.get("notExist") == null)); JsonNode notExistNode = rootNode.path("notExist"); System.out.println("notExistNode的value:" + notExistNode.asText()); System.out.println("isMissingNode方法返回true:" + notExistNode.isMissingNode()); //當key存在,而value為null的時候,get和path都會返回一個NullNode節點。 System.out.println(rootNode.get("nullNode") instanceof NullNode); System.out.println(rootNode.path("nullNode") instanceof NullNode); } }
流式API
流式API是一套比較底層的API,速度快,但是使用起來特別麻煩。它主要是有兩個核心類,一個是JsonGenerator,用來生成json,另一個是JsonParser,用來讀取json內容。話不多說,直接上程式碼演示。
package com.xymxyg.json; import com.fasterxml.jackson.core.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * @author guangsheng.tang * JsonParser和Generator的優點是速度快,缺點是寫起來真的很複雜。 */ public class StreamApi { public static void main(String[] args) throws IOException { JsonFactory factory = new JsonFactory(); String s = "{\"id\": 1,\"class\": \"3\"}}"; //這裡就舉一個比較簡單的例子,Generator的用法就是一個一個write即可。 File file = new File("/json.txt"); JsonGenerator jsonGenerator = factory.createGenerator(file,JsonEncoding.UTF8); //物件開始 jsonGenerator.writeStartObject(); //寫入一個鍵值對 jsonGenerator.writeStringField("name","小光"); //物件結束 jsonGenerator.writeEndObject(); //關閉jsonGenerator jsonGenerator.close(); //讀取剛剛寫入的json FileInputStream inputStream = new FileInputStream(file); int i = 0; final int SIZE = 1024; byte[] buf = new byte[SIZE]; StringBuilder sb = new StringBuilder(); while ((i = inputStream.read(buf)) != -1) { System.out.println(new String(buf,i)); } inputStream.close(); //JsonParser解析的時候,思路是把json字串根據邊界符分割為若干個JsonToken,這個JsonToken是一個列舉型別。 //下面這個小例子,可以看出JsonToken是如何劃分型別的。 JsonParser parser = factory.createParser(s); while (!parser.isClosed()){ JsonToken token = parser.currentToken(); System.out.println(token); parser.nextToken(); } JsonParser jsonParser = factory.createParser(s); //下面是一個解析的例項 while (!jsonParser.isClosed()) { JsonToken token = jsonParser.nextToken(); if (JsonToken.FIELD_NAME.equals(token)) { String currentName = jsonParser.currentName(); token = jsonParser.nextToken(); if ("id".equals(currentName)) { System.out.println("id:" + jsonParser.getValueAsInt()); } else if ("name".equals(currentName)) { System.out.println("name:" + jsonParser.getValueAsString()); } else if ("array".equals(currentName)) { token = jsonParser.nextToken(); while (!JsonToken.END_ARRAY.equals(token)) { System.out.println("array:" + jsonParser.getValueAsString()); token = jsonParser.nextToken(); } } } } } }
JackSon的常用註解
JackSon提供了一些的註解,可以用在類上或者是在欄位上。通常是資料繫結的時候使用。下面幾個是最常用的幾個
@JsonInclude(Include.NON_EMPTY)
僅在屬性不為空時序列化此欄位,對於字串,即null或空字串
@JsonIgnore
序列化時忽略此欄位
@JsonProperty(value = “user_name”)
指定序列化時的欄位名,預設使用屬性名
總結
JackSon使用起來還是十分方便的,提供的功能也很多,在使用的時候,需要結合自己的業務場景,選擇合適的解析方式。
參考資料
http://blog.lifw.org/post/63088058v
https://www.yiibai.com/jackson/
到此這篇關於淺談JackSon的幾種用法的文章就介紹到這了,更多相關JackSon 用法內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!