Jackson API 詳細匯總 與 使用介紹


Jackson 概述 與 依賴

1、市面上用於在 Java 中解析 Json 的第三方庫,隨便一搜不下幾十種,其中的佼佼者有 Google 的 Gson Alibaba 的 Fastjson 以及本文的 jackson

2、三者不相伯仲,隨着掌握一個都能滿足項目中的 json 解析操作,因為 Spring Boot Web 組件默認使用的是  jackson,所以掌握 Jackjson 是非常有必要的

 

3、gson 和 fastjson 使用時只需要導入一個 jar 包(或者一個依賴)即可,而 jackson 卻不是全部集成在一個 jar (一個應用)內,而是分為不同的功能模塊,需要使用哪些功能,則導入對應的 jar 包(或依賴)。

FasterXml Github 地址:https://github.com/FasterXML,jackson 所有的功能模塊都在其中

比如 jackson-core 模塊:https://github.com/FasterXML/jackson-core,其中提供了 maven 依賴:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <!-- 如可以使用最新的 2.9.7、2.9.8 版本 -->
  <version>${jackson.version.core}</version>
</dependency>

jackson-core 二進制 jar 包下載地址:http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/

其余的 jackson-xxx 模塊也是同理,在其相應的項目主頁中,都提供 maven 依賴與下載 jar 地址。

4、看了上面 Spring Boot Web 組件依賴 jackson 的情況就知道,使用 Jackson 導入以下 3 個主要模塊基本滿足開發:

jackson-core                      #maven 依賴二進制jar包

jackson-annotations          #maven依賴二進制jar包

jackson-databind               #maven依賴二進制jar包

5、其中 jackson-databind 內部依賴了 jackson-annotations 與  jackson-core,所以 Maven 應用時,只要導入 databind 一個,則同時也導入了 annotations 與  core 依賴。

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.0</version>
</dependency>

Jackson 使用前情提要

1、默認情況下,ObjectMapper 在序列化對象時,將實體所有的字段一 一序列化,無論這些字段是否有值,是否為 null。

2、如果實體的某個字段沒有提供 getter 方法,則該字段不會被序列化。

3、Spring Boot Web 組件默認使用  jackson 進行對象的序列化與反序列化,即頁面傳入的參數,會自動反序列化為后台對象,后台傳給前端的對象,也會序列化后輸出。所以需要注意返回給頁面的對象默認不能使用 Jackson 以外的 Json 庫序列化,比如返回一個 Gson 的 JsonObject 給前端,則會報錯,因為顯然 Jackson 序列化時會失敗。

4、Jackson 提供三種不同的方法來操作 JSON: 

1)流式API - 使用 Stream(流) 的方式對 Json 的每一個組成部分進行最細粒度的控制,JsonParser 讀取數據,JsonGenerator 寫入數據。

2)樹模型 - 將 JSON 文件在內存里以樹的形式表示,通過 JsonNode 處理單個Json節點,類似於 XML 的 DOM 解析器。(常用)

3)databind 模塊 - ObjectMapper 讀/寫 JSON 是 POJO 序列化與反序列化 json 最方便的方式。(常用)

ObjectMapper 序列化對象

1、ObjectMapper 主要用於對 Java 對象(比如 POJO、List、Set、Map 等等)進行序列化與反序列化。

2、ObjectMapper 除了能在 json 字符串與 Java 對象之間進行轉換,還能將 json 字符串與 JsonNode 進行轉換。

Java 對象與 Json 字符串的轉換
String writeValueAsString(Object value)

1、用於將任何 Java 對象(如 POJO、List、Set、Map等)序列化為 json 字符串,如果對象中某個屬性的值為 null,則默認也會序列化為 null;

2、如果 value 為 null,返回序列化的結果也返回 null

byte[] writeValueAsBytes(Object value)

將 java 對象序列化為 字節數組

writeValue(File resultFile, Object value)

將 java 對象序列化並輸出指定文件中

writeValue(OutputStream out, Object value)

將 java 對象序列化並輸出到指定字節輸出流中

writeValue(Writer w, Object value)

將 java 對象序列化並輸出到指定字符輸出流中
T readValue(String content, Class<T> valueType)

1、從給定的 JSON 字符串反序列化為 Java 對象;

2、content 為空或者為 null,都會報錯
3、valueType 表示反序列化的結果對象,可以是任何 java 對象,比如 POJO、List、Set、Map 等等.

T readValue(byte[] src, Class<T> valueType) 將 json 內容的字節數組反序列化為 java 對象
T readValue(File src, Class<T> valueType) 將本地 json 內容的文件反序列化為 java 對象
T readValue(InputStream src, Class<T> valueType) 將 json 內容的字節輸入流反序列化為 java 對象
T readValue(Reader src, Class<T> valueType) 將 json 內容的字符輸入流反序列化為 java 對象

T readValue(URL src, Class<T> valueType)
通過網絡 url 地址將 json 內容反序列化為 java 對象
Json 字符串內容反序列化為 Json 節點對象
JsonNode readTree(String content) 將 JSON 字符串反序列化為 JsonNode 對象,即 json 節點對象
JsonNode readTree(URL source) 對網絡上的 json 文件進行反序列化為 json 節點對象
JsonNode readTree(InputStream in) 對 json 文件輸入流進行反序列化為 json 節點對象
JsonNode readTree(byte[] content) 對 json 字節數組反序列化為 json 節點對象
JsonNode readTree(File file) 將本地 json 文件反序列為為 json 節點對象
Java 對象與 Json 節點對象的轉換
T convertValue(Object fromValue, Class<T> toValueType) 將 Java 對象(如 POJO、List、Map、Set 等)序列化為 Json 節點對象。
T treeToValue(TreeNode n, Class<T> valueType)

json 樹節點對象轉 Java 對象(如 POJO、List、Set、Map 等等)

TreeNode 樹節點是整個 json 節點對象模型的根接口。

API 演示源碼:/src/main/java/com/wmx/jackson/ObjectMapperTest.java

package com.wmx.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;

import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * {@link ObjectMapper} 用於對 Java 對象(比如 POJO、List、Set、Map 等等)進行序列化與反序列化
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2020/7/16 14:34
 */
@SuppressWarnings("all")
public class ObjectMapperTest {
    /**
     * POJO 對象轉 json 字符串
     * String writeValueAsString(Object value)
     * 1、該方法可用於將任何 Java 值、對象序列化為 json 字符串,如果對象中某個屬性的值為 null,則默認也會序列化為 null
     * 2、value 為 null,返回 null
     *
     * @throws JsonProcessingException
     */
    @Test
    public void writeValueAsString1() throws JsonProcessingException {
        User user = new User(1000, "張三", new Date(), null);
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(user);
        System.out.println(json);
        //{"uId":1000,"uName":"張三","birthday":1594881355832,"price":null}
    }

    /**
     * String writeValueAsString(Object value)
     * 1、 Java 值、對象序列化為 json 字符串,value 可以是任意的 java 對象,比如 POJO、list、Map、Set 等等
     */
    @Test
    public void writeValueAsString2() {
        try {
            List<User> userList = new ArrayList<>(2);
            User user1 = new User(1000, "張三", null, 7777.88F);
            User user2 = new User(2000, "李四", new Date(), 9800.78F);
            userList.add(user1);
            userList.add(user2);

            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(userList);
            //[{"uId":1000,"uName":"張三","birthday":null,"price":7777.88},{"uId":2000,"uName":"李四","birthday":1594882217908,"price":9800.78}]
            System.out.println(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * String writeValueAsString(Object value)
     * 1、 Java 值、對象序列化為 json 字符串,value 可以是任意的 java 對象,比如 POJO、list、Map、Set 等等
     */
    @Test
    public void writeValueAsString3() throws JsonProcessingException {
        try {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("uId", 9527);
            dataMap.put("uName", "華安");
            dataMap.put("birthday", new Date());
            dataMap.put("price", 9998.45F);
            dataMap.put("marry", null);

            ObjectMapper objectMapper = new ObjectMapper();
            //{"birthday":1594884443501,"uId":9527,"uName":"華安","price":9998.45,"marry":null}
            String json = objectMapper.writeValueAsString(dataMap);
            System.out.println(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * writeValue(File resultFile, Object value)
     * 1、 Java java 對象,比如 POJO、list、Map、Set 等等 序列化並輸出到指定文件中
     * 2、文件不存在時,會自動新建
     */
    @Test
    public void writeValueAsString4() throws JsonProcessingException {
        try {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("uId", 9527);
            dataMap.put("uName", "華安2");
            dataMap.put("birthday", new Date());
            dataMap.put("price", 9998.45F);
            dataMap.put("marry", null);

            File homeDirectory = FileSystemView.getFileSystemView().getHomeDirectory();
            File jsonFile = new File(homeDirectory, "wmx2.json");

            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.writeValue(jsonFile, dataMap);
            System.out.println("輸出 json 文件:" + jsonFile.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * T readValue(String content, Class<T> valueType)
     * 1、從給定的 JSON 內容字符串反序列化為對象
     * 2、content 為空或者為 null,都會報錯
     * 3、valueType 表示反序列號的結果對象,可以是任何 java 對象,比如 POJO、List、Set、Map 等等.
     */
    @Test
    public void readValue1() {
        try {
            String json = "{\"uId\":1000,\"uName\":\"張三\",\"birthday\":1594881355832,\"price\":null}";
            ObjectMapper objectMapper = new ObjectMapper();
            User user = objectMapper.readValue(json, User.class);
            //User{uId=1000, uName='張三', birthday=Thu Jul 16 14:35:55 CST 2020, price=null}
            System.out.println(user);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * T readValue(String content, Class<T> valueType)
     * 1、從給定的 JSON 內容字符串反序列化為對象
     * 2、content 為空或者為 null,都會報錯
     * 3、valueType 表示反序列號的結果對象,可以是任何 java 對象,比如 POJO、List、Set、Map 等等.
     */
    @Test
    public void readValue2() {
        try {
            String json = "[{\"uId\":1000,\"uName\":\"張三\",\"birthday\":null,\"price\":7777.88},{\"uId\":2000,\"uName\":\"李四\",\"birthday\":1594882217908,\"price\":9800.78}]";
            ObjectMapper objectMapper = new ObjectMapper();
            List<User> userList = objectMapper.readValue(json, List.class);
            //{uId=2000, uName=李四, birthday=1594882217908, price=9800.78}
            System.out.println(userList.get(1));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * T readValue(String content, Class<T> valueType)
     * 1、從給定的 JSON 內容字符串反序列化為對象
     * 2、content 為空或者為 null,都會報錯
     * 3、valueType 表示反序列號的結果對象,可以是任何 java 對象,比如 POJO、List、Set、Map 等等.
     */
    @Test
    public void readValue3() {
        try {
            String json = "{\"birthday\":1594884443501,\"uId\":9527,\"uName\":\"華安\",\"price\":9998.45,\"marry\":null}";
            ObjectMapper objectMapper = new ObjectMapper();
            Map map = objectMapper.readValue(json, Map.class);
            //{birthday=1594884443501, uId=9527, uName=華安, price=9998.45, marry=null}
            System.out.println(map);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * T readValue(File src, Class<T> valueType):將本地 json 內容文件反序列為 Java 對象
     */
    @Test
    public void readTree4() {
        try {
            String json = "[{\"uId\":1000,\"uName\":\"張三\",\"birthday\":null,\"price\":7777.88},{\"uId\":2000,\"uName\":\"李四\",\"birthday\":1594882217908,\"price\":9800.78}]";
            File homeDirectory = FileSystemView.getFileSystemView().getHomeDirectory();
            File jsonFile = new File(homeDirectory, "wmx.json");
            if (!jsonFile.exists()) {
                FileWriter fileWriter = new FileWriter(jsonFile);
                fileWriter.write(json);
                fileWriter.flush();
                fileWriter.close();
                System.out.println("輸出 json 文件:" + jsonFile.getAbsolutePath());
            }
            List<User> userList = new ObjectMapper().readValue(jsonFile, List.class);
            //{uId=2000, uName=李四, birthday=1594882217908, price=9800.78}
            System.out.println(userList.get(1));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * JsonNode readTree(String content):將 JSON 內容反序列化為 JsonNode 對象
     *
     * @throws IOException
     */
    @Test
    public void readTree1() throws IOException {
        //被解析的 json 格式的字符串
        String json = "{\"notices\":[{\"title\":\"停水\",\"day\":\"1\"},{\"title\":\"停電\",\"day\":\"3\"},{\"title\":\"停網\",\"day\":\"2\"}]}";
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(json);
        System.out.println(jsonNode);
    }

    /**
     * JsonNode readTree(URL source) :對網絡上的 json 文件進行反序列化為 json 節點對象
     */
    @Test
    public void readTree2() {
        try {
            URL url = new URL("http://t.weather.sojson.com/api/weather/city/101030100");
            JsonNode jsonNode = new ObjectMapper().readTree(url);
            System.out.println(jsonNode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * JsonNode readTree(File file):將本地 json 文件反序列化為 json 節點對象
     */
    @Test
    public void readTree3() {
        try {
            String json = "[{\"uId\":1000,\"uName\":\"張三\",\"birthday\":null,\"price\":7777.88},{\"uId\":2000,\"uName\":\"李四\",\"birthday\":1594882217908,\"price\":9800.78}]";
            File homeDirectory = FileSystemView.getFileSystemView().getHomeDirectory();
            File jsonFile = new File(homeDirectory, "wmx.json");
            if (!jsonFile.exists()) {
                FileWriter fileWriter = new FileWriter(jsonFile);
                fileWriter.write(json);
                fileWriter.flush();
                fileWriter.close();
                System.out.println("輸出 json 文件:" + jsonFile.getAbsolutePath());
            }
            JsonNode jsonNode = new ObjectMapper().readTree(jsonFile);
            System.out.println(jsonNode.get(0));//{"uId":1000,"uName":"張三","birthday":null,"price":7777.88}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * T treeToValue(TreeNode n, Class<T> valueType):json 節點對象轉 Java 對象(如 POJO、List、Set、Map 等等)
     */
    @Test
    public void test() {
        try {
            ObjectNode objectNode = JsonNodeFactory.instance.objectNode();
            objectNode.put("uId", 3200);
            objectNode.put("uName", "李世民");
            objectNode.put("birthday", new Date().getTime());

            User user = new ObjectMapper().treeToValue(objectNode, User.class);
            //User{uId=3200, uName='李世民', birthday=Fri Jul 17 20:34:13 CST 2020, price=null}
            System.out.println(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    /**
     * T convertValue(Object fromValue, Class<T> toValueType)
     * 1、將 Java 對象(如 POJO、List、Map、Set 等)序列化為 Json 節點對象,通常有以下兩種方式:
     * 2、一種方式是先序列化為 json 字符串,然后 readTree 反序列化為 Json 節點
     * 3、還有就是使用此種方式進行轉換,將 java 對象直接轉換為 json 節點。
     */
    @Test
    public void convertValue1() {
        User user = new User(1000, "張三", new Date(), null);
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.convertValue(user, JsonNode.class);
        //{"uId":1000,"uName":"張三","birthday":1594967015825,"price":null}
        System.out.println(jsonNode);
    }

    @Test
    public void convertValue2() {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("uId", 9527);
        dataMap.put("uName", "華安");
        dataMap.put("birthday", new Date());
        dataMap.put("price", 9998.45F);
        dataMap.put("marry", null);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode objectNode = objectMapper.convertValue(dataMap, JsonNode.class);
        //{"birthday":1594950930586,"uId":9527,"uName":"華安","price":9998.45,"marry":null}
        System.out.println(objectNode);
    }

    @Test
    public void convertValue3() {
        List<User> userList = new ArrayList<>(2);
        User user1 = new User(1000, "張三", null, 7777.88F);
        User user2 = new User(2000, "李四", new Date(), 9800.78F);
        userList.add(user1);
        userList.add(user2);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode objectNode = objectMapper.convertValue(userList, JsonNode.class);
        //[{"uId":1000,"uName":"張三","birthday":null,"price":7777.88},{"uId":2000,"uName":"李四","birthday":1594967168878,"price":9800.78}]
        System.out.println(objectNode);
    }

}
View Code

JsonNode 樹模型 Json 節點

1、JsonNode 表示 json 節點,整個節點模型的根接口為 TreeNode,json 節點主要用於手動構建 json 對象。

2、JsonNode 有各種數據類型的實現類,其中最常用的就是 ObjectNode 與 ArrayNode,前者表示 json 對象,后者表示 json 對象數組。

3、json 節點對象可以通過 JsonNodeFactory 創建,如 JsonNodeFactory.instance.objectNode();

JsonNode json節點通用方法
JsonNode get(String fieldName) 用於訪問對象節點的指定字段的值,如果此節點不是對象、或沒有指定字段名的值,或沒有這樣名稱的字段,則返回 null。
JsonNode get(int index)JsonNode get(int index)

訪問數組節點的指定索引位置上的值,對於其他節點,總是返回 null.

如果索引小於0,或等於、大於節點大小,則返回 null,對於任何索引都不會引發異常。

boolean isArray() 判斷此節點是否為 {@link ArrayNode} 數組節點
boolean isObject() 如果此節點是對象節點,則返回 true,否則返回 false
int size() 獲取 json 節點的大小,比如 json 對象中有多少鍵值對,或者 json 數組中有多少元素。
ObjectNode deepCopy() json 節點對象深度復制,相當於克隆
Iterator<String> fieldNames() 獲取 json 對象中的所有 key
Iterator<JsonNode> elements() 如果該節點是JSON數組或對象節點,則訪問此節點的所有值節點,對於對象節點,不包括字段名(鍵),只包括值,對於其他類型的節點,返回空迭代器。
boolean has(int index) 檢查此節點是否為數組節點,並是否含有指定的索引。

boolean has(String fieldName)

檢查此節點是否為 JSON 對象節點並包含指定屬性的值。

將 json 屬性的值轉為 java 數據類型

int asInt()
int asInt(int defaultValue)

asInt():嘗試將此節點的值轉換為 int 類型,布爾值 false 轉換為 0,true 轉換為 1。如果不能轉換為 int(比如值是對象或數組等結構化類型),則返回默認值 0 ,不會引發異常。

asInt(int defaultValue):設置默認值

boolean asBoolean()
boolean asBoolean(boolean defaultValue)

嘗試將此節點的值轉換為 Java 布爾值,0以外的整數映射為true,0映射為false,字符串“true”和“false”映射到相應的值。

如果無法轉換為布爾值(包括對象和數組等結構化類型),則返回默認值 false,不會引發異常。

可以自己設置默認值。

asText(String defaultValue)

String asText()

如果節點是值節點(isValueNode 返回 true),則返回容器值的有效字符串表示形式,否則返回空字符串。

long asLong()

long asLong(long defaultValue)

與 asInt 同理

double asDouble()
double asDouble(double defaultValue)

嘗試將此節點的值轉換為 double,布爾值轉換為0.0(false)和1.0(true),字符串使用默認的Java 語言浮點數解析規則進行解析。

如果表示不能轉換為 double(包括對象和數組等結構化類型),則返回默認值 0.0,不會引發異常。

BigInteger bigIntegerValue()

返回此節點的整數值(BigDecimal),當且僅當此節點為數字時(isNumber}返回true)。

對於其他類型,返回 BigInteger.ZERO。

boolean booleanValue() 用於訪問 JSON 布爾值(值文本“true”和“false”)的方法,對於其他類型,始終返回false
BigDecimal decimalValue() 返回此節點的浮點值 BigDecimal, 當且僅當此節點為數字時(isNumber 返回true),對於其他類型,返回 BigDecimal.ZERO
double doubleValue() 返回此節點的64位浮點(雙精度)值,當且僅當此節點為數字時(isNumber返回true),對於其他類型,返回0.0。
float floatValue() 返回此節點的32位浮點值,當且僅當此節點為數字時(isNumber返回true),對於其他類型,返回0.0。
int intValue()
long longValue()
Number numberValue()
short shortValue()
String textValue()
返回此節點的 int、long、Number、short、String 值。
ObjectNode 對象節點常用方法

ObjectNode put(String fieldName, String v)
ObjectNode put(String fieldName, int v)

1、將字段的值設置為指定的值,如果字段已經存在,則更新值,value 可以為 null.

2、其它 8  種基本數據類型以及 String、BigDecimal、BigInteger 都可以 put,但是沒有 Date 類型

3、Date 日期類型只能通過 Long 長整型設置

ArrayNode putArray(String fieldName) 構造新的 ArrayNode 子節點,並將其作為此 ObjectNode 的字段添加。
ObjectNode putNull(String fieldName): 為指定字段添加 null 值,put 
ObjectNode putObject(String fieldName) 構造新的 ObjectNode 字節的,並將其作為此 ObjectNode 的字段添加。
替換與刪除元素
JsonNode replace(String fieldName, JsonNode value) 將特定屬性的值替換為傳遞的值,字段存在時更新,不存在時新增
JsonNode set(String fieldName, JsonNode value) 設置指定屬性的值為 json 節點對象,字段存在時更新,不存在時新增,類似 replace 方法
JsonNode setAll(Map<String,? extends JsonNode> properties) 同時設置多個 json 節點
JsonNode setAll(ObjectNode other) 添加給定對象(other)的所有屬性,重寫這些屬性的任何現有值.
ArrayNode withArray(String propertyName) 將 json 節點轉為 json 數組對象
ObjectNode with(String propertyName) 將 json 節點轉為 ObjectNode 對象
JsonNode remove(String fieldName) 刪除指定的 key,返回被刪除的節點
ObjectNode remove(Collection<String> fieldNames) 同時刪除多個字段
ObjectNode removeAll() 刪除所有字段屬性
JsonNode without(String fieldName): 刪除指定的 key,底層也是 remove
ObjectNode without(Collection<String> fieldNames) 同時刪除多個字段,底層也是 removeAll
ArrayNode 數組節點常用方法
ArrayNode add(String v)

將指定的字符串值添加到此 json 數組的末尾,其它數據類型也是同理。

除了可以添加 String 類型,還有 Java 的 8 種基本數據類型,以及 BigDecimal、BigInteger、JsonNode 類型。

ArrayNode addAll(ArrayNode other) 用於添加給定數組的所有子節點
ArrayNode addNull() 該方法將在此數組節點的末尾添加 null 值。
ArrayNode addArray() 構造新的 ArrayNode 子節點,並將其添加到此數組節點的末尾
ObjectNode addObject() 構造一個新的 ObjectNode 字節的,並將其添加到此數組節點的末尾

API 演示源碼:/src/main/java/com/wmx/jackson/JsonNodeTest.java

package com.wmx.jackson;

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.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.NumericNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * {@link ArrayNode}、{@link ObjectNode}、{@link NumericNode} 等等都是 {@link JsonNode} 的子類
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2020/7/16 16:57
 */
@SuppressWarnings("all")
public class JsonNodeTest {

    /**
     * JsonNodeFactory.instance: 創建單例的 JsonNodeFactory 工廠
     * ObjectNode objectNode() : 構造空的 JSON 對象
     * ObjectNode put(String fieldName, String v): 將字段的值設置為指定的字符串值,如果字段已經存在,則更新值
     * ObjectNode put(String fieldName, int v):其它數據類型也是同理
     * ArrayNode putArray(String fieldName):構造 ArrayNode 並將其作為此 ObjectNode 的字段添加。
     * ObjectNode putNull(String fieldName): 為指定字段添加 null 值
     * ArrayNode add(String v) :將指定的字符串值添加到此數組的末尾,其它數據類型也是同理。
     */
    @Test
    public void objectNode1() {
        JsonNodeFactory jsonNodeFactory = JsonNodeFactory.instance;
        ObjectNode objectNode = jsonNodeFactory.objectNode();
        objectNode.put("name", "張三");
        objectNode.put("age", 25);
        objectNode.putNull("marry");

        ArrayNode arrayNode = objectNode.putArray("urls");
        arrayNode.add("http://tomcat.org/tomcat.png#1");
        arrayNode.add("http://tomcat.org/tomcat.png#2");
        arrayNode.add("http://tomcat.org/tomcat.png#3");

        //{"name":"張三","age":25,"marry":null,"urls":["http://tomcat.org/tomcat.png#1","http://tomcat.org/tomcat.png#2","http://tomcat.org/tomcat.png#3"]}
        System.out.println(objectNode.toString());
    }

    @Test
    public void objectNode2() {
        JsonNodeFactory jsonNodeFactory = JsonNodeFactory.instance;
        ObjectNode objectNode_root = jsonNodeFactory.objectNode();
        ArrayNode arrayNode = objectNode_root.putArray("notices");

        ObjectNode objectNodeChild = jsonNodeFactory.objectNode();
        objectNodeChild.put("title", "放假通知");
        objectNodeChild.put("content", "寒假放假於本月3浩開始.");
        arrayNode.add(objectNodeChild);

        //{"notices":[{"title":"放假通知","content":"寒假放假於本月3浩開始."}]}
        System.out.println(objectNode_root);
    }

    /**
     * JsonNode replace(String fieldName, JsonNode value):將特定屬性的值替換為傳遞的值,字段存在時更新,不存在時新增
     * JsonNode set(String fieldName, JsonNode value):設置指定屬性的值為 json 節點對象,字段存在時更新,不存在時新增,類似 replace 方法
     * JsonNode setAll(Map<String,? extends JsonNode> properties):同時設置多個 json 節點
     */
    @Test
    public void objectNode3() {
        try {
            String json = "{\"notices\":[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            ObjectNode objectNode = (ObjectNode) jsonNode;

            ObjectNode node = JsonNodeFactory.instance.objectNode();
            node.put("code", 200);
            objectNode.set("status", node);
            //{"notices":[{"title":"放假通知","content":"寒假放假於本月3浩開始."}],"status":{"code":200}}
            System.out.println(objectNode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * JsonNode setAll(ObjectNode other):添加給定對象(other)的所有屬性,重寫這些屬性的任何現有值
     */
    @Test
    public void objectNode4() {
        try {
            String json = "{\"notices\":[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            ObjectNode objectNode = (ObjectNode) jsonNode;

            ObjectNode node = JsonNodeFactory.instance.objectNode();
            node.put("code", 200);
            objectNode.setAll(node);
            //{"notices":[{"title":"放假通知","content":"寒假放假於本月3浩開始."}],"code":200}
            System.out.println(objectNode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * JsonNode get(String fieldName):
     * 1、用於訪問對象節點的指定字段的值,如果此節點不是對象、或沒有指定字段名的值,或沒有這樣名稱的字段,則返回 null。
     * boolean isArray(): 判斷此節點是否為 {@link ArrayNode} 數組節點
     * int size():獲取數組節點的大小
     * int asInt():
     * 1、嘗試將此節點的值轉換為 int 類型,布爾值 false 轉換為 0,true 轉換為 1。
     * 2、如果不能轉換為 int(比如值是對象或數組等結構化類型),則返回默認值 0 ,不會引發異常。
     * String asText():如果節點是值節點(isValueNode返回true),則返回容器值的有效字符串表示形式,否則返回空字符串。
     * 其它數據類型也是同理
     */
    @Test
    public void objectNode5() {
        try {
            String json = "{\"notices\":[{\"title\":\"停水\",\"day\":\"12\"},{\"title\":\"停電\",\"day\":\"32\"},{\"title\":\"停網\",\"day\":\"22\"}]}";
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode jsonNode = (ObjectNode) objectMapper.readTree(json);

            JsonNode notices = jsonNode.get("notices");
            if (notices != null && notices.isArray()) {
                for (int i = 0; i < notices.size(); i++) {
                    JsonNode childNode = notices.get(i);
                    String title = childNode.get("title").asText();
                    Integer day = childNode.get("day").asInt();
                    System.out.println((i + 1) + ":" + title + "\t" + day);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ArrayNode withArray(String propertyName): 將 json 節點轉為 json 數組對象
     * ObjectNode with(String propertyName):將 json 節點轉為 ObjectNode 對象
     */
    @Test
    public void objectNode6() {
        try {
            String json = "{\"notices\":[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);

            ObjectNode objectNode = (ObjectNode) jsonNode;
            ArrayNode arrayNode = objectNode.withArray("notices");
            for (int i = 0; i < arrayNode.size(); i++) {
                //{"title":"放假通知","content":"寒假放假於本月3浩開始."}
                JsonNode node = arrayNode.get(i);
                System.out.println(node);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * JsonNode remove(String fieldName):刪除指定的 key,返回被刪除的節點
     * JsonNode without(String fieldName):
     * ObjectNode remove(Collection<String> fieldNames):同時刪除多個字段
     * ObjectNode without(Collection<String> fieldNames):同時刪除多個字段
     * ObjectNode removeAll(): 刪除所有字段屬性
     */
    @Test
    public void objectNode7() {
        try {
            String json = "{\"notices\":[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            ObjectNode objectNode = (ObjectNode) jsonNode;

            JsonNode remove = objectNode.remove("notices");
            System.out.println(remove);//[{"title":"放假通知","content":"寒假放假於本月3浩開始."}]
            System.out.println(objectNode);//{}

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ObjectNode deepCopy():json 節點對象深度復制,相當於克隆
     * Iterator<String> fieldNames(): 獲取 json 對象中的所有 key
     */
    @Test
    public void objectNode8() {
        try {
            String json = "{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            ObjectNode objectNode = (ObjectNode) jsonNode;
            ObjectNode deepCopy = objectNode.deepCopy();
            deepCopy.put("summary", "同意");
            System.out.println(objectNode);//{"title":"放假通知","content":"寒假放假於本月3浩開始."}
            System.out.println(deepCopy);//{"title":"放假通知","content":"寒假放假於本月3浩開始.","summary":"同意"}

            Iterator<String> fieldNames = deepCopy.fieldNames();
            while (fieldNames.hasNext()) {
                String next = fieldNames.next();
                System.out.println(next + "=" + deepCopy.get(next));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void objectNode9() {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("code", 200);
        dataMap.put("msg", "成功");

        ObjectNode objectNode = JsonNodeFactory.instance.objectNode();
        objectNode.putPOJO("data", dataMap);

        System.out.println(objectNode);
        JsonNode jsonNode = objectNode.get("data");
    }

    /**
     * double asDouble(): 嘗試將此節點的值轉換為 double,布爾值轉換為0.0(false)和1.0(true),字符串使用默認的Java 語言浮點數解析規則進行解析。
     * 如果表示不能轉換為 double(包括對象和數組等結構化類型),則返回默認值 0.0,不會引發異常。
     * BigDecimal decimalValue() :返回此節點的浮點值 BigDecimal, 當且僅當此節點為數字時(isNumber 返回true),對於其他類型,返回 BigDecimal.ZERO
     */
    @Test
    public void test10() {
        ObjectNode objectNode = JsonNodeFactory.instance.objectNode();
        objectNode.put("id", 1000);
        objectNode.put("salay", 15000.456);

        double salay = objectNode.get("salay").asDouble();
        BigDecimal bigDecimal = objectNode.get("salay").decimalValue();
        System.out.println(salay + "," + bigDecimal);//15000.456,15000.456
    }

    /**
     * boolean has(int index):檢查此節點是否為數組節點,並是否含有指定的索引。
     * boolean has(String fieldName):檢查此節點是否為 JSON 對象節點並包含指定屬性的值。
     */
    @Test
    public void test11() {
        ArrayNode arrayNode = JsonNodeFactory.instance.arrayNode();
        arrayNode.add(12).add("中國").addNull().add(345.5667);
        System.out.println(arrayNode);//[12,"中國",null,345.5667]

        System.out.println(arrayNode.has(1));//true
        System.out.println(arrayNode.has(2));//true
        System.out.println(arrayNode.has(4));//false
    }

    /**
     * Iterator<JsonNode> elements():如果該節點是JSON數組或對象節點,則訪問此節點的所有值節點
     * 對於對象節點,不包括字段名(鍵),只包括值,對於其他類型的節點,返回空迭代器。
     */
    @Test
    public void test12() {
        try {
            String json = "{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\",\"id\":23400}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            Iterator<JsonNode> elements = jsonNode.elements();
            while (elements.hasNext()) {
                JsonNode next = elements.next();
                //"放假通知" "寒假放假於本月3浩開始." 23400
                System.out.print(next + " ");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ArrayNode addAll(ArrayNode other): 用於添加給定數組的所有子節點
     */
    @Test
    public void test13() {
        try {
            String json = "[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]";
            JsonNode jsonNode = new ObjectMapper().readTree(json);

            ArrayNode rootArrayNode = JsonNodeFactory.instance.arrayNode();
            rootArrayNode.add(1000);
            if (jsonNode.isArray()) {
                ArrayNode arrayNode = (ArrayNode) jsonNode;
                rootArrayNode.addAll(arrayNode);
            }
            //[1000,{"title":"放假通知","content":"寒假放假於本月3浩開始."}]
            System.out.println(rootArrayNode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ArrayNode addNull() :該方法將在此數組節點的末尾添加空值。
     */
    @Test
    public void test14() {
        try {
            String json = "[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            if (jsonNode.isArray()) {
                ArrayNode arrayNode = (ArrayNode) jsonNode;
                arrayNode.addNull();
                //[{"title":"放假通知","content":"寒假放假於本月3浩開始."},null]
                System.out.println(arrayNode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ArrayNode addArray(): 構造新的 ArrayNode 節點,並將其添加到此數組節點的末尾
     */
    @Test
    public void test15() {
        try {
            String json = "[{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}]";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            if (jsonNode.isArray()) {
                ArrayNode arrayNode = (ArrayNode) jsonNode;
                ArrayNode addArray = arrayNode.addArray();
                addArray.add(31.4F);
                addArray.add("優秀");
                //[{"title":"放假通知","content":"寒假放假於本月3浩開始."},[31.4,"優秀"]]
                System.out.println(arrayNode);
                //[31.4,"優秀"]
                System.out.println(addArray);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ObjectNode putObject(String fieldName):構造新的 ObjectNode 字節的,並將其作為此 ObjectNode 的字段添加。
     */
    @Test
    public void test16() {
        try {
            String json = "{\"title\":\"放假通知\",\"content\":\"寒假放假於本月3浩開始.\"}";
            JsonNode jsonNode = new ObjectMapper().readTree(json);
            if (jsonNode.isObject()) {
                ObjectNode objectNode = (ObjectNode) jsonNode;
                ObjectNode persons = objectNode.putObject("person");
                persons.put("name", "張三");
                persons.put("age", 34);
                //{"title":"放假通知","content":"寒假放假於本月3浩開始.","person":{"name":"張三","age":34}}
                System.out.println(objectNode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
View Code

Jsonson 注解設置 POJO 屬性

1、ObjectMapper  序列化 POJO 對象為 json 字符串時,Date 日期類型默認會轉為 long 長整型,json 字符串反序列化為 POJO 時自動將長整型的日期轉為 Date 類型。

2、Map 對象序列化為 json 字符串時,Map 中的日期值也會默認轉為 long 長整型, ObjectMapper.readValue(String content, Class<T> valueType):反序列化為 Map 對象時,長整型的日期仍舊是長整型,不會轉回 Date。ObjectMapper.readTree(String content) 反序列化為 json 節點時,原來 Map 中的長整型的日期也會是長整型。

3、JsonNode 節點對象 put 數據時,有 8  種基本數據類型以及 String、BigDecimal、BigInteger,但是沒有 Date 類型,所以日期類型只能通過 Long 長整型設置,但是轉 POJO 對象時仍然會自動轉為 Date 類型。

4、Google 的 gson 默認不會序列化對象中值為 null 的字段,而 jackson 則不管值是否為 null,都會序列化。

5、@JsonFormat 注解加到指定對象的屬性上可以指定日期序列化的格式。

6、JsonInclude(JsonInclude.Include.NON_NULL) 添加到 POJO 對象上,表示對值為 null 的屬性不進行序列化。

 

 參考文章:https://blog.csdn.net/wangmx1993328/article/details/88598625


免責聲明!

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



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