专业的JAVA编程教程与资源

网站首页 > java教程 正文

36. JSON 解析速成,三库实战揭秘

temp10 2025-08-02 21:40:59 java教程 1 ℃ 0 评论

哈喽 大家好!

我是老陈,这节课一起来学习Java 中的 JSON 解析技术,JSON是一种轻量级的数据交换格式,易于人类阅读和编写,同时也易于机器解析和生成,像 “数据交换的通用语言”,让不同系统间能顺畅传递信息。

36. JSON 解析速成,三库实战揭秘

36.1 JSON 基础与语法规则

旁白:首先我们先来了解什么是JSON,JSON 就像 “带标签的包裹”,每个数据项都有明确的键名,拆包时能精准定位内容。它的语法简洁且严格,就像国际快递的统一包装规范。 它有两种基本结构:

对象(Object):用花括号 {} 包裹,由键值对组成,键和值之间用冒号 : 分隔,多个键值对之间用逗号 , 分隔。

数组(Array):用方括号 [] 包裹,由值组成,值之间用逗号 , 分隔。

JSON 值可以是:字符串(必须用双引号) 、数字(整数或浮点数) 、布尔值(true 或 false) 、数组 、对象和null 。

{
  "userInfo": {
    "name": "John Doe",
    "age": 30,
    "isStudent": false,
    "hobbies": [
      "reading",
      "coding",
      "swimming"
    ]
  },
  "fruits": [
    {
      "name": "Apple",
      "price": 1.5
    },
    {
      "name": "Banana",
      "price": 0.8
    },
    {
      "name": "Orange",
      "price": 1.2
    }
  ]
}

36.2 Java 中的 JSON 解析库对比

Java 中 JSON 的解析与生成的开发库挺多的,了解一下即可。在实际开发中,FastJSON、Gson和Jackson都有人使用。我们一般用的是FastJSON。

package com.json.demo;

// 导入所需的JSON解析库
import com.alibaba.fastjson2.JSON;       // FastJSON2库
import com.fasterxml.jackson.databind.ObjectMapper;  // Jackson库
import com.google.gson.Gson;             // Gson库
import java.util.concurrent.TimeUnit;    // 用于时间单位转换

/**
 * @author 今日头条:老陈说编程
 * JSON解析器性能测试类
 * 用于对比三种主流Java JSON解析库的解析性能
 */
public class JSONParser {
    // 测试用的JSON字符串,包含多种数据类型和复杂结构
    private static final String JSON_DATA = "{" +
            "\"id\": 1001," +                           // 数字类型
            "\"name\": \"产品性能测试报告\"," +            // 字符串类型
            "\"active\": true," +                        // 布尔类型
            "\"price\": 99.99," +                        // 浮点数类型
            "\"discount\": 0.85," +                      // 浮点数类型
            "\"tags\": [\"性能测试\", \"JSON\", \"Java\"]," + // 字符串数组
            "\"createdAt\": \"2023-10-15T08:30:45.123Z\"," + // 日期时间字符串
            "\"updatedAt\": \"2023-10-15T14:22:18.456Z\"," +
            "\"author\": {" +                            // 嵌套对象
            "\"id\": 501," +
            "\"name\": \"张工程师\"," +
            "\"email\": \"zhang@example.com\"," +
            "\"department\": \"研发部\"," +
            "\"skills\": [\"Java\", \"JSON\", \"性能优化\"]" +
            "}," +
            "\"metrics\": {" +                           // 嵌套对象,包含数值指标
            "\"average\": 89.7," +
            "\"min\": 65.2," +
            "\"max\": 99.8," +
            "\"median\": 90.5," +
            "\"p95\": 96.3," +
            "\"samples\": 1568" +
            "}," +
            "\"results\": [" +                           // 对象数组
            "{" +
            "\"testCase\": \"解析速度测试\"," +
            "\"passed\": true," +
            "\"durationMs\": 127," +
            "\"error\": null," +                         // null值
            "\"details\": {" +
            "\"iterations\": 10000," +
            "\"avgPerIterationNs\": 12680" +
            "}" +
            "}," +
            "{" +
            "\"testCase\": \"内存占用测试\"," +
            "\"passed\": true," +
            "\"durationMs\": 89," +
            "\"error\": null," +
            "\"details\": {" +
            "\"peakMemoryMb\": 45.3," +
            "\"avgMemoryMb\": 32.8" +
            "}" +
            "}," +
            "{" +
            "\"testCase\": \"并发处理测试\"," +
            "\"passed\": false," +
            "\"durationMs\": 215," +
            "\"error\": \"线程同步问题\"," +
            "\"details\": {" +
            "\"threads\": 20," +
            "\"failedCount\": 3" +
            "}" +
            "}" +
            "]," +
            "\"configuration\": {" +                     // 配置信息对象
            "\"timeout\": 5000," +
            "\"retryCount\": 3," +
            "\"thresholds\": {" +
            "\"performance\": 100," +
            "\"accuracy\": 99.9" +
            "}," +
            "\"enabledModules\": [\"core\", \"advanced\", \"network\"]" +
            "}" +
            "}";

    // 测试次数:每种JSON解析器将执行10万次解析操作
    private static final int TEST_COUNT = 100000;

    /**
     * 主方法:程序入口点
     * 分别测试Jackson、Gson和FastJSON的解析性能并输出结果
     */
    public static void main(String[] args) throws Exception {
        // Jackson性能测试
        long jacksonStart = System.nanoTime();  // 记录开始时间(纳秒级)
        ObjectMapper jacksonMapper = new ObjectMapper();  // 创建Jackson解析器实例

        // 执行TEST_COUNT次解析操作
        for (int i = 0; i < TEST_COUNT; i++) {
            // 将JSON字符串解析为Object对象
            jacksonMapper.readValue(JSON_DATA, Object.class);
        }
        long jacksonEnd = System.nanoTime();    // 记录结束时间

        // Gson性能测试
        long gsonStart = System.nanoTime();     // 记录开始时间
        Gson gson = new Gson();                 // 创建Gson解析器实例

        // 执行TEST_COUNT次解析操作
        for (int i = 0; i < TEST_COUNT; i++) {
            // 将JSON字符串解析为Object对象
            gson.fromJson(JSON_DATA, Object.class);
        }
        long gsonEnd = System.nanoTime();       // 记录结束时间

        // FastJSON性能测试
        long fastJsonStart = System.nanoTime(); // 记录开始时间

        // 执行TEST_COUNT次解析操作
        for (int i = 0; i < TEST_COUNT; i++) {
            // 将JSON字符串解析为对象(FastJSON静态方法)
            JSON.parse(JSON_DATA);
        }
        long fastJsonEnd = System.nanoTime();   // 记录结束时间

        // 输出各解析器的耗时(转换为毫秒)
        System.out.println("Jackson解析耗时:" +
                TimeUnit.NANOSECONDS.toMillis(jacksonEnd - jacksonStart) + "ms");
        System.out.println("Gson解析耗时:" +
                TimeUnit.NANOSECONDS.toMillis(gsonEnd - gsonStart) + "ms");
        System.out.println("FastJSON解析耗时:" +
                TimeUnit.NANOSECONDS.toMillis(fastJsonEnd - fastJsonStart) + "ms");
    }
}

36.3 核心操作:解析与生成的双向转换

JSON 操作就像 “数据的双向翻译”—— 解析是将 JSON 文本转为 Java 对象(反序列化),生成是将 Java 对象转为 JSON 文本(序列化),两者构成数据交换的闭环。以Jackson为例进行解析和生成。

package com.json.demo;

// 导入Jackson库的ObjectMapper类,用于JSON的序列化和反序列化
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Map;

/**
 * @author 今日头条:老陈说编程
 * JSON基本操作
 * 该类展示了使用Jackson库进行JSON与Java对象之间的相互转换
 * 包括:JSON字符串解析为Java对象、Java对象序列化为JSON字符串、JSON字符串解析为Map对象
 */
public class JSONBasicOps {
    // 内部静态User类,用于演示JSON与对象之间的转换
    static class User {
        private String name;  // 用户名
        private int age;      // 年龄

        // 构造方法
        public User() {
        }

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        // getter和setter方法
        public String getName() {
            return name;
        }

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

        public int getAge() {
            return age;
        }

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

        // 重写toString方法,方便打印对象信息
        @Override
        public String toString() {
            return "User{name='" + name + "', age=" + age + "}";
        }
    }

    public static void main(String[] args) throws IOException {
        // 创建ObjectMapper实例,这是Jackson库的核心类,用于处理JSON
        ObjectMapper mapper = new ObjectMapper();

        // 1. 解析JSON字符串为User对象
        // 定义一个JSON格式的字符串
        String jsonStr = "{\"name\":\"张三\",\"age\":25}";
        // 使用readValue方法将JSON字符串转换为User对象
        // 第一个参数是JSON字符串,第二个参数是目标类的Class对象
        User user = mapper.readValue(jsonStr, User.class);
        // 打印解析结果,会调用User类的toString方法
        System.out.println("解析结果:" + user);

        // 2. 将User对象序列化为JSON字符串
        // 创建一个新的User对象
        User newUser = new User("李四", 30);
        // 使用writeValueAsString方法将对象转换为JSON字符串
        String generatedJson = mapper.writeValueAsString(newUser);
        // 打印生成的JSON字符串
        System.out.println("生成JSON:" + generatedJson);

        // 3. 解析JSON字符串为Map对象(适合处理字段不固定的JSON)
        // 将JSON字符串转换为Map对象,键为字段名,值为对应的值
        Map<?, ?> map = mapper.readValue(jsonStr, Map.class);
        // 打印解析后的Map对象
        System.out.println("解析为Map:" + map);
    }
} 

36.4 复杂结构处理:嵌套与数组解析

处理复杂 JSON 就像 “拆解多层包裹”—— 遇到嵌套对象要逐层解析,遇到数组需按顺序处理每个元素,关键是理清数据结构关系。 以 FastJSON 为例,解析嵌套对象和数组等JSON数据。

package com.json.demo;

// 导入fastjson2相关类库,用于JSON解析

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;

import java.util.List;

/**
 * 复杂JSON解析
 * 使用fastjson2解析包含嵌套结构的JSON数据
 */
public class ComplexJSONParser {

    /**
     * 产品实体类
     * 对应JSON数据的结构,包含基本类型、集合和嵌套对象
     */
    static class Product {
        private int id;               // 产品ID
        private String name;          // 产品名称
        private List<String> tags;    // 产品标签列表
        private Spec spec;            // 产品规格(嵌套对象)

        public Product(int id, String name, List<String> tags, Spec spec) {
            this.id = id;
            this.name = name;
            this.tags = tags;
            this.spec = spec;
        }

        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 List<String> getTags() {
            return tags;
        }

        public void setTags(List<String> tags) {
            this.tags = tags;
        }

        public Spec getSpec() {
            return spec;
        }

        public void setSpec(Spec spec) {
            this.spec = spec;
        }

        /**
         * 重写toString方法,方便打印对象信息
         */
        @Override
        public String toString() {
            return "Product{id=" + id + ", name='" + name + "', tags=" + tags + ", spec=" + spec + "}";
        }
    }

    /**
     * 产品规格实体类
     * 作为Product类的嵌套对象存在
     */
    static class Spec {
        private String brand;  // 品牌
        private String model;  // 型号

        public Spec(String brand, String model) {
            this.brand = brand;
            this.model = model;
        }

        public String getBrand() {
            return brand;
        }

        public void setBrand(String brand) {
            this.brand = brand;
        }

        public String getModel() {
            return model;
        }

        public void setModel(String model) {
            this.model = model;
        }

        /**
         * 重写toString方法,方便打印规格信息
         */
        @Override
        public String toString() {
            return "Spec{brand='" + brand + "', model='" + model + "'}";
        }
    }

    /**
     * 主方法,程序入口
     */
    public static void main(String[] args) {
        // 定义一个复杂的JSON字符串,包含基本类型、数组和嵌套对象
        String complexJson = "{\"id\":1001,\"name\":\"智能手机\",\"price\":4999.00," +
                "\"tags\":[\"电子产品\",\"通讯设备\"],\"spec\":{\"brand\":\"ABC\",\"model\":\"X100\"}}";

        // 1. 解析为自定义对象(推荐方式)
        // 使用JSON.parseObject方法直接将JSON字符串转换为Product对象
        // 优点:代码简洁,无需手动处理每个字段
        Product product = JSON.parseObject(complexJson, Product.class);
        System.out.println("解析为对象:" + product);

        // 2. 手动解析嵌套结构
        // 第一步:将JSON字符串解析为JSONObject对象
        JSONObject jsonObject = JSON.parseObject(complexJson);

        // 第二步:从JSONObject中获取基本类型字段
        int id = jsonObject.getIntValue("id");
        String name = jsonObject.getString("name");

        // 第三步:解析数组类型字段(tags数组)
        JSONArray tagsArray = jsonObject.getJSONArray("tags");
        List<String> tags = tagsArray.toList(String.class);  // 转换为List<String>

        // 第四步:解析嵌套对象(spec对象)
        JSONObject specObj = jsonObject.getJSONObject("spec");
        String brand = specObj.getString("brand");  // 从嵌套对象中获取字段

        // 打印手动解析的结果
        System.out.println("手动解析:id=" + id + ", name=" + name + ", brand=" + brand + ", tags=" + tags);
    }
} 

36.5 队列与栈场景:JSON 数组的特殊处理

JSON 数组在队列、栈场景中就像 “有序排列的货物”—— 解析时按 FIFO(队列)或 LIFO(栈)顺序处理,生成时需保持元素顺序的正确性。 以Gson 为例,将JSON数组转换为List类型,用作队列;将JSON数组转换为LinkedList类型,用作栈。

package com.json.demo;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * 何使用Gson库处理JSON数组,并将其作为队列和栈两种数据结构使用
 */
public class JSONArrayQueueStack {

    /**
     * 内部类,表示消息实体
     */
    static class Message {
        private String id;
        private String content;

        // 显式定义带两个参数的构造器
        public Message(String id, String content) {
            this.id = id;
            this.content = content;
        }

        // getter和setter方法
        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }

        @Override
        public String toString() {
            return "Message{id='" + id + "', content='" + content + "'}";
        }
    }

    public static void main(String[] args) {
        // 创建Gson对象用于JSON处理
        Gson gson = new Gson();

        // 示例JSON数组字符串,包含两条消息
        String messageArray = "[{\"id\":\"msg1\",\"content\":\"你好\"},{\"id\":\"msg2\",\"content\":\"再见\"}]";

        // ===== 第一部分:演示队列(FIFO)的操作 =====
        System.out.println("===== 队列(FIFO)操作 =====");

        // 将JSON数组转换为List类型,用作队列
        List<Message> messageQueue = gson.fromJson(messageArray, new TypeToken<List<Message>>() {
        }.getType());
        System.out.println("队列初始状态:" + messageQueue);

        // 入队操作:在队列尾部添加新元素
        messageQueue.add(new Message("msg3", "新消息"));

        // 出队操作:移除并返回队列头部元素
        Message firstMsg = messageQueue.remove(0);
        System.out.println("出队消息:" + firstMsg + ",剩余队列:" + messageQueue);

        // ===== 第二部分:演示栈(LIFO)的操作 =====
        System.out.println("\n===== 栈(LIFO)操作 =====");

        // 将JSON数组转换为LinkedList类型,用作栈
        // 注意:LinkedList实现了Deque接口,可以作为栈使用
        LinkedList<Message> messageStack = gson.fromJson(messageArray, new TypeToken<LinkedList<Message>>() {
        }.getType());
        System.out.println("栈初始状态:" + messageStack);

        // 入栈操作:使用push方法将元素添加到栈顶(链表头部)
        messageStack.push(new Message("msg3", "新消息"));

        // 出栈操作:使用pop方法移除并返回栈顶元素(链表头部)
        Message topMsg = messageStack.pop();
        System.out.println("出栈消息:" + topMsg + ",剩余栈:" + messageStack);
    }
}

总结JSON 解析的适用场景

接口数据交换:前后端交互、微服务接口返回JSON格式数据;

配置文件:存储结构化配置(如SpringBoot的application.json);

日志记录:结构化日志便于后续分析和检索;

数据导出:将数据库记录转为JSON供第三方系统使用。

下期将学习数据库,记得点赞关注,评论区留下你遇到的JSON问题,我们一起解


#java##计算机##程序员##今日头条##热门##热搜##职场提升##上热搜#

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表