网站首页 > java教程 正文
哈喽 大家好!
我是老陈,这节课一起来学习Java 中的 JSON 解析技术,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问题,我们一起解
猜你喜欢
- 2025-08-02 Dart编程学习笔记05-列表与映射表
- 2025-08-02 深度解析 Java 21 新特性,助力互联网软件开发升级
- 2025-08-02 系统性能优化与Java代码编写性能考虑
- 2025-08-02 前端问答:Map 和 Object 有啥不同?
- 2025-08-02 GitHub爆火!银四巨作:拼多多/蚂蚁/百度面经分享
- 2025-08-02 什么是unordered_map?用大白话说
- 2025-08-02 MapReduce过程详解及其性能优化(详细)
- 2025-08-02 轻松解读源码系列之Java集合接口&抽象类(1)—Map和Collection
- 2025-08-02 golang常用数据结构之map详细讲解
你 发表评论:
欢迎- 08-02从上百个字段到1个CLOB:Oracle JSON存储实战指南
- 08-02什么是JSON?
- 08-02Qt解析JSON
- 08-02JSON是什么?JSON的使用详解
- 08-02mysql 之json字段详解(多层复杂检索)
- 08-02MySQL的json查询之json_array
- 08-02C#解析多层嵌套的JSON数组
- 08-02Dart编程学习笔记05-列表与映射表
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)