Jackson使用


版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/m0_37076574/article/details/81317403
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,\"name\": \"小明\",\"array\": [\"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,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," +
"\"test\":\"I'm test\",\"nullNode\":null,\"base\": {\"major\": \"物聯網\",\"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,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," +
"\"test\":\"I'm test\",\"nullNode\":null,\"base\": {\"major\": \"物聯網\",\"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,0,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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM