Java 使用 Jackson 处理 Json 数据


Json 全称是 JavaScript Object Notation,是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。它易于阅读和编写,同时也易于计算机解析和生成,并能够有效的提升网络传输效率,简洁清晰的层次结构,使得 JSON 成为目前主流的数据交换语言。

本篇博客主要介绍 Java 使用第三方 Jackson 的 jar 包,实现 Java Bean 对象与 Json 字符串之间的数据转换,以及在不使用 Java Bean 对象作为转换目标的情况下,读取 Json 字段获取数据的实现方式。在博客的末尾会提供源代码。

Jackson 的官网地址:https://github.com/codehaus/jackson


一、搭建示例工程

新建一个 maven 工程,并导入 Jackson 的 jar 包。

Jackson 的 jar 包一共有 3 个,分别为:

jackson-core:这个最底层核心 jar 包,提供基于"流模式"解析的相关 API,其 jar 包地址为:

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core

jackson-annotations:这个是注解包,提供标准注解功能,其 jar 包地址为:

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations

jackson-databind:这个数据绑定包, 提供基于【对象绑定】解析的相关 API和【树模型"】解析的相关 API,其 jar 包地址:

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

由于 jackson-databind 依赖 jackson-core 和 jackson-annotations,当我们使用 maven 导入 jackson-databind 的 jar 包引用之后, jackson-core 和 jackson-annotations 这 2 个 jar 包也会自动添加到 maven 项目工程中。

因此我们只需要导入 jackson-databind 的 jar 包即可。我导入的是最新的 jackson-databind 的 jar 包,另外为了方便测试,也导入了最新的 juint 的 jar 包,具体内容如下:



    com.fasterxml.jackson.core
    jackson-databind
    2.13.1




    junit
    junit
    4.13.2
    test

配置好引用的 jar 包后,打开右侧的 Maven 窗口,刷新一下,这样 Maven 会自动下载所需的 jar 包文件。

搭建好的项目工程整体目录比较简单,具体如下图所示:

项目工程结构简单介绍:

com.jobs.bean.employee 员工实体类

test 目录下的文件介绍:
com.jobs.jsonTest 类是专门用来编写 junit 单元测试方法,用来测试所编写的 json 处理方法
resources 下的 data.json 文件中存储一段 json 数据,用于在本 demo 中进行解析


二、细节展示

com.jobs.bean.employee 员工实体类的内容如下:

package com.jobs.bean;

import java.util.Objects;

public class employee {
    private String name; //姓名
    private Integer age; //年龄

    public employee() {
    }

    public employee(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    //重写 equals 和 hashCode 方法,用于 employee 对象的去重:
    //当两个 employee 对象的 name 和 age 属性值一样的话,认为是相同的 employee 对象
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        employee employee = (employee) o;
        return Objects.equals(name, employee.name) && Objects.equals(age, employee.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    //重新 toString() 方法,用于打印出 employee 对象的细节,方便查看
    @Override
    public String toString() {
        return "employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

test 下面 resources 目录下的 data.json 内容如下:

{
  "status": 0,
  "msg": "成功",
  "data": {
    "address": {
      "street": "黄金屋",
      "city": "科技复兴",
      "province": "地球"
    },
    "friends": [
      "侯胖胖",
      "任肥肥",
      "蔺赞赞",
      "李敦敦",
      "杨帅帅"
    ]
  }
}

com.jobs.jsonTest 类是编写处理 json 数据的测试类,具体内容如下:

package com.jobs;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jobs.bean.employee;
import org.junit.Test;

import java.io.*;
import java.util.*;

public class jsonTest {

    //创建对象绑定模型对象 ObjectMapper 对象的实例,方便下面的测试方法直接使用
    private ObjectMapper mapper = new ObjectMapper();

    //JavaBean 与 Json 之间的转换
    @Test
    public void test01() throws Exception {

        //将 bean 对象转换为 json 字符串
        employee emp = new employee("侯胖胖", 40);
        String json = mapper.writeValueAsString(emp);
        System.out.println(json);

        //将字符串转换为 bean 对象
        employee result = mapper.readValue(json, employee.class);
        System.out.println(result);
    }

    //Java 自带的数据结构(里面是 Java 自带的数据类型)与 Json 之间的转换
    @Test
    public void test02() throws Exception {

        List list = new ArrayList<>();
        list.add("候胖胖");
        list.add("任肥肥");
        list.add("李敦敦");

        //将 List 转换为 json 字符串
        String listJson = mapper.writeValueAsString(list);
        System.out.println(listJson);

        //将 json 转换为 List
        List listResult = mapper.readValue(listJson, List.class);
        System.out.println(listResult);

        System.out.println("---------------------------------");

        Map map = new HashMap<>();
        map.put("侯胖胖", 40);
        map.put("任肥肥", 38);
        map.put("李敦敦", 26);

        //将 Map 转换为 json 字符串
        String mapJson = mapper.writeValueAsString(map);
        System.out.println(mapJson);

        //将 json 转换为 Map
        Map mapResult = mapper.readValue(mapJson, Map.class);
        System.out.println(mapResult);

        System.out.println("---------------------------------");

        Set set = new HashSet<>();
        set.add("候胖胖");
        set.add("任肥肥");
        set.add("李敦敦");
        set.add("任肥肥");
        set.add("候胖胖");

        //将 Set 转换为 json 字符串
        String setJson = mapper.writeValueAsString(set);
        System.out.println(setJson);

        //将 json 转换为 Set
        Set setResult = mapper.readValue(setJson, Set.class);
        System.out.println(setResult);
    }

    //Java 自带的数据结构(里面是自定义的 JavaBean 类对象)与 Json 之间的转换
    //需要使用 TypeReference 来将进行 json 与自定义 JavaBean 类对象之间的对应
    @Test
    public void test03() throws Exception {
        List list = new ArrayList<>();
        list.add(new employee("侯胖胖", 40));
        list.add(new employee("任肥肥", 38));
        list.add(new employee("李敦敦", 26));

        //将 List 转换为 json 字符串
        String listJson = mapper.writeValueAsString(list);
        System.out.println(listJson);

        //将 json 转换为 List
        List listResult =
                mapper.readValue(listJson, new TypeReference>() {});
        System.out.println(listResult);

        System.out.println("---------------------------------");

        Map map = new HashMap<>();
        map.put("破坏之王", new employee("侯胖胖", 40));
        map.put("埋坑专家", new employee("任肥肥", 38));
        map.put("拆蛋大神", new employee("李敦敦", 26));

        //将 Map 转换为 json 字符串
        String mapJson = mapper.writeValueAsString(map);
        System.out.println(mapJson);

        //将 json 转换为 Map
        Map mapResult =
                mapper.readValue(mapJson, new TypeReference>() {});
        System.out.println(mapResult);

        System.out.println("---------------------------------");

        Set set = new HashSet<>();
        set.add(new employee("侯胖胖", 40));
        set.add(new employee("任肥肥", 38));
        set.add(new employee("李敦敦", 26));
        set.add(new employee("任肥肥", 38));
        set.add(new employee("侯胖胖", 40));

        //将 Set 转换为 json 字符串
        String setJson = mapper.writeValueAsString(set);
        System.out.println(setJson);

        //将 json 转换为 Set
        Set setResult =
                mapper.readValue(setJson, new TypeReference>() {});
        System.out.println(setResult);
    }

    //不使用 JavaBean ,采用 JsonNode 读取 Json 字段的数据
    @Test
    public void test04() throws Exception {

        //获取 data.json 的文件路径
        String dataPath = jsonTest.class
                .getClassLoader().getResource("data.json").getPath();

        //从 data.json 文件中读取 json 数据
        StringBuilder sb = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader(dataPath))) {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        }

        System.out.println("-------------从文件中获取到的 json 数据:");

        String json = sb.toString().replace(" ", "");
        System.out.println(json); //把 data.json 文件中的 json 数据打印出来

        System.out.println("-------------解析 json 数据:");

        //json 具有树模型的特征,因此可以按照树形结构进行解析
        JsonNode root = mapper.readTree(json);

        //获取 int 类型的 status 值
        int status = root.get("status").asInt();
        System.out.println("status 为 " + status);

        //获取 String 类型的 msg 值
        String msg = root.get("msg").asText();
        System.out.println("msg 为 " + msg);

        //获取 address 数据
        JsonNode address = root.get("data").get("address");
        String street = address.get("street").asText();
        String city = address.get("city").asText();
        String province = address.get("province").asText();
        System.out.println("address 数据如下:");
        System.out.println("\t" + "province 为 " + province);
        System.out.println("\t" + "city 为 " + city);
        System.out.println("\t" + "street 为 " + street);

        //获取 friends 数组数据
        JsonNode friends = root.get("data").get("friends");
        System.out.println("friends 数据如下:");
        for (JsonNode item : friends) {
            System.out.println("\t" + item.asText());
        }
    }
}

需要注意的一点就是:如果想把 json 转换为自定义的 JavaBean 对象,需要使用 TypeReference 。

上面代码中最后一个方法,模拟的实际场景是:当我们调用相关接口或从其它某种途径获取到 Json 数据时,不想创建与 Json 字段相对应的实体类时,可以采用 Json 树模型的方案来进行解析,获取相关 Json 字段的值。

本 demo 的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/jacksondemo.zip



相关