淺談JackSon的幾種用法
JackSon介紹
本文使用的JackSon版本為2.9.6。
JackSon是解析JSON和XML的一個(gè)框架,優(yōu)點(diǎn)是簡(jiǎn)單易用,性能較高。
JackSon處理JSON的方式
JackSon提供了三種JSON的處理方式。分別是數(shù)據(jù)綁定,樹(shù)模型,流式API。下面會(huì)分別介紹這三種方式。
JackSon數(shù)據(jù)綁定
數(shù)據(jù)綁定用于JSON轉(zhuǎn)化,可以將JSON與POJO對(duì)象進(jìn)行轉(zhuǎn)化。數(shù)據(jù)綁定有兩種,簡(jiǎn)單數(shù)據(jù)綁定和完整數(shù)據(jù)綁定。
完整數(shù)據(jù)綁定
package com.xymxyg.json; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; /** * @author guangsheng.tang * 下面是最常用的場(chǎng)景,將json字符串映射為對(duì)象,或者是將對(duì)象轉(zhuǎn)化為json字符串。這是完整數(shù)據(jù)綁定。 缺點(diǎn):這種方法十分方便,但是擴(kuò)展性不強(qiáng),增加一個(gè)字段便要修改POJO對(duì)象,這個(gè)操作有一定風(fēng)險(xiǎn)性。并且解析的時(shí)候,如果json缺少POJO中的某字段,映射出的對(duì)象對(duì)應(yīng)值默認(rèn)為null,直接使用有一定風(fēng)險(xiǎn)。如果json對(duì)象多了某一字段,解析過(guò)程中會(huì)拋出UnrecognizedPropertyException異常。并且如果json較為復(fù)雜的話,POJO對(duì)象會(huì)顯得特別臃腫。 */ public class CompleteDataBind { public static void main(String[] args) throws IOException { String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]}"; ObjectMapper mapper = new ObjectMapper(); //Json映射為對(duì)象 Student student = mapper.readValue(s, Student.class); //對(duì)象轉(zhuǎn)化為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()) + '}'; } }
簡(jiǎn)單數(shù)據(jù)綁定
簡(jiǎn)單數(shù)據(jù)綁定就是將json字符串映射為java核心的數(shù)據(jù)類型。
json類型 | Java類型 |
---|---|
object | LinkedHashMap |
array | ArrayList |
string | String |
number | Integer,Long,Double |
true|false | Boolean |
null | null |
下面演示一個(gè)例子,將json轉(zhuǎn)化為一個(gè)Map。通過(guò)Map來(lái)讀取。
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 * 簡(jiǎn)單數(shù)據(jù)綁定的示例,不用POJO對(duì)象,直接映射為一個(gè)Map,然后從Map中獲取。 */ public class SimpleDataBind { public static void main(String[] args) throws IOException { Map<String, Object> map = new HashMap<>(16); String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," + "\"test\":\"I'm test\",\"base\": {\"major\": \"物聯(lián)網(wǎng)\",\"class\": \"3\"}}"; ObjectMapper mapper = new ObjectMapper(); map = mapper.readValue(s, map.getClass()); //獲取id Integer studentId = (Integer) map.get("id"); System.out.println(studentId); //獲取數(shù)據(jù) 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); //嵌套的對(duì)象獲取 Map base = (Map) map.get("base"); String major = (String) base.get("major"); System.out.println(major); } }
樹(shù)模型
針對(duì)JackSon的樹(shù)模型結(jié)構(gòu),我下面寫了一個(gè)比較完善的例子。同樣Java樹(shù)模型有優(yōu)點(diǎn),也有缺點(diǎn)。
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樹(shù)模型結(jié)構(gòu),可以通過(guò)get,JsonPointer等進(jìn)行操作,適合用來(lái)獲取大Json中的字段,比較靈活。缺點(diǎn)是如果需要獲取的內(nèi)容較多, * 會(huì)顯得比較繁瑣。 */ public class TreeModel { public static void main(String[] args) throws IOException { ObjectMapper mapper = new ObjectMapper(); //以下是對(duì)象轉(zhuǎn)化為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("使用樹(shù)型模型構(gòu)建的json:"+json); //以下是樹(shù)模型的解析Json String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," + "\"test\":\"I'm test\",\"nullNode\":null,\"base\": {\"major\": \"物聯(lián)網(wǎng)\",\"class\": \"3\"}}"; //讀取rootNode JsonNode rootNode = mapper.readTree(s); //通過(guò)path獲取 System.out.println("通過(guò)path獲取值:" + rootNode.path("name").asText()); //通過(guò)JsonPointer可以直接按照路徑獲取 JsonPointer pointer = JsonPointer.valueOf("/base/major"); JsonNode node = rootNode.at(pointer); System.out.println("通過(guò)at獲取值:" + node.asText()); //通過(guò)get可以取對(duì)應(yīng)的value JsonNode classNode = rootNode.get("base"); System.out.println("通過(guò)get獲取值:" + classNode.get("major").asText()); //獲取數(shù)組的值 System.out.print("獲取數(shù)組的值:"); 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方法看起來(lái)很相似,其實(shí)他們的細(xì)節(jié)不同,get方法取不存在的值的時(shí)候,會(huì)返回null。而path方法會(huì) //返回一個(gè)"missing node",該"missing node"的isMissingNode方法返回值為true,如果調(diào)用該node的asText方法的話, // 結(jié)果是一個(gè)空字符串。 System.out.println("get方法取不存在的節(jié)點(diǎn),返回null:" + (rootNode.get("notExist") == null)); JsonNode notExistNode = rootNode.path("notExist"); System.out.println("notExistNode的value:" + notExistNode.asText()); System.out.println("isMissingNode方法返回true:" + notExistNode.isMissingNode()); //當(dāng)key存在,而value為null的時(shí)候,get和path都會(huì)返回一個(gè)NullNode節(jié)點(diǎn)。 System.out.println(rootNode.get("nullNode") instanceof NullNode); System.out.println(rootNode.path("nullNode") instanceof NullNode); } }
流式API
流式API是一套比較底層的API,速度快,但是使用起來(lái)特別麻煩。它主要是有兩個(gè)核心類,一個(gè)是JsonGenerator,用來(lái)生成json,另一個(gè)是JsonParser,用來(lái)讀取json內(nèi)容。話不多說(shuō),直接上代碼演示。
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的優(yōu)點(diǎn)是速度快,缺點(diǎn)是寫起來(lái)真的很復(fù)雜。 */ public class StreamApi { public static void main(String[] args) throws IOException { JsonFactory factory = new JsonFactory(); String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," + "\"test\":\"I'm test\",\"nullNode\":null,\"base\": {\"major\": \"物聯(lián)網(wǎng)\",\"class\": \"3\"}}"; //這里就舉一個(gè)比較簡(jiǎn)單的例子,Generator的用法就是一個(gè)一個(gè)write即可。 File file = new File("/json.txt"); JsonGenerator jsonGenerator = factory.createGenerator(file, JsonEncoding.UTF8); //對(duì)象開(kāi)始 jsonGenerator.writeStartObject(); //寫入一個(gè)鍵值對(duì) jsonGenerator.writeStringField("name", "小光"); //對(duì)象結(jié)束 jsonGenerator.writeEndObject(); //關(guān)閉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,0,i)); } inputStream.close(); //JsonParser解析的時(shí)候,思路是把json字符串根據(jù)邊界符分割為若干個(gè)JsonToken,這個(gè)JsonToken是一個(gè)枚舉類型。 //下面這個(gè)小例子,可以看出JsonToken是如何劃分類型的。 JsonParser parser = factory.createParser(s); while (!parser.isClosed()){ JsonToken token = parser.currentToken(); System.out.println(token); parser.nextToken(); } JsonParser jsonParser = factory.createParser(s); //下面是一個(gè)解析的實(shí)例 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提供了一些的注解,可以用在類上或者是在字段上。通常是數(shù)據(jù)綁定的時(shí)候使用。下面幾個(gè)是最常用的幾個(gè)
@JsonInclude(Include.NON_EMPTY)
僅在屬性不為空時(shí)序列化此字段,對(duì)于字符串,即null或空字符串
@JsonIgnore
序列化時(shí)忽略此字段
@JsonProperty(value = “user_name”)
指定序列化時(shí)的字段名,默認(rèn)使用屬性名
總結(jié)
JackSon使用起來(lái)還是十分方便的,提供的功能也很多,在使用的時(shí)候,需要結(jié)合自己的業(yè)務(wù)場(chǎng)景,選擇合適的解析方式。
參考資料
http://blog.lifw.org/post/63088058v
https://www.yiibai.com/jackson/
到此這篇關(guān)于淺談JackSon的幾種用法的文章就介紹到這了,更多相關(guān)JackSon 用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
完美解決Logback configuration error detected的問(wèn)題
這篇文章主要介紹了完美解決Logback configuration error detected的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例
這篇文章主要介紹了Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08Java項(xiàng)目之java+springboot+ssm實(shí)現(xiàn)理財(cái)管理系統(tǒng)設(shè)計(jì)
這篇文章主要介紹了Java項(xiàng)目java+springboot+ssm實(shí)現(xiàn)理財(cái)管理系統(tǒng)設(shè)計(jì),使用了當(dāng)前較為流行的spring boot,spring,spring mvc,mybatis,shiro框架分頁(yè)處理使用了pagehelper進(jìn)行操作,需要的朋友可以參考一下2022-03-03解決mybatis?update并非所有字段需要更新問(wèn)題
這篇文章主要介紹了解決mybatis?update并非所有字段需要更新問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Spring?循環(huán)依賴之AOP實(shí)現(xiàn)詳情
這篇文章主要介紹了Spring?循環(huán)依賴之AOP實(shí)現(xiàn)詳情,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的盆友可以參考一下2022-07-07java使用stream判斷兩個(gè)list元素的屬性并輸出方式
這篇文章主要介紹了java使用stream判斷兩個(gè)list元素的屬性并輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06SpringBoot前后端json數(shù)據(jù)交互的全過(guò)程記錄
現(xiàn)在大多數(shù)互聯(lián)網(wǎng)項(xiàng)目都是采用前后端分離的方式開(kāi)發(fā),下面這篇文章主要給大家介紹了關(guān)于SpringBoot前后端json數(shù)據(jù)交互的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03Java實(shí)現(xiàn)微信公眾號(hào)自定義菜單的創(chuàng)建方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)微信公眾號(hào)自定義菜單的創(chuàng)建方法,結(jié)合實(shí)例形式分析了java創(chuàng)建微信公眾號(hào)自定義菜單的具體步驟、實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-10-10