Java与JSON
关于 JSON,最重要的是要理解它是一种数据格式,不是一种编程语言**。虽然具有相同的语法形式,但 JSON 并不从属于 JavaScript。而且,并不是只有 JavaScript 才使用 JSON,毕竟 JSON 只是一种数据格式。很多编程语言都有针对 JSON 的解析器和序列化器。
JSON 是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量。
对象(object):一个对象包含一系列非排序的键/值对
,一个对象以
{
开始,并以 }
结束。每个键/值对之间使用
:
分区。多个键值对之间通过 ,
分割。需要注意的是JSON 的键是一个 String
类型的字符串

值(value):可以是双引号括起来的字符串(string)
、数值(number)
、true
、false
、
null
、对象(object)
或者数组(array)
。这些结构可以嵌套使用。

ECMAScript 5 定义了一个原生的 JSON 对象; JSON对象包含两个方法:
用于解析 JavaScript
Object Notation (JSON) 的 parse()
方法,以及将 对象/值
转换为 JSON字符串的 stringify()
方法。
关于JSON对象——JsonElement
JSON字符串和JSON对象的区别
JSON 字符串是由双引号包围的文本,其格式严格遵循 JSON 规范。它其实就是 JSON 对象的字符串表示,在网络传输或者数据存储时经常会用到。
1 | // 这是一个JSON字符串 |
特点:
- 必须使用双引号来包裹键和字符串值。
- 不能包含函数、undefined 或者 NaN 等特殊值。
- 可以被序列化为二进制格式,例如 MessagePack。
JSON 对象是内存中的数据结构,在不同的编程语言里有不同的表现形式,像 JavaScript 对象、Java 中的 Map、Python 中的字典等。
1 | // JavaScript中的JSON对象 |
特点:
- 可以直接对属性进行访问,例如
person.name
。 - 能够包含特殊值,比如
null
、函数、undefined
。 - 生命周期和内存管理由宿主语言负责。
JSON 字符串是数据的文本表示形式,主要用于数据的传输和存储。
JSON 对象是内存中的数据结构,用于数据的操作和处理。
两者通过解析(parse)和序列化(stringify)进行转换。
顺便说一下,JSON
数组其实就是包含了多个
JSON
对象的一个集合,数组是以 数组括号 []
括起来的
1 | [{ |
JSON
数组并一定是要相同的
JSON
对象的集合,也可以是不同的对象
JSON 在 Java 开发中的作用
JSON 以什么作用出现在开发中
数据交换的核心格式
在现代 Web 应用里,JSON 是前后端进行数据交互的主要格式。前端发送请求时,会把数据封装成 JSON 字符串;后端处理完请求后,也会把响应数据序列化为 JSON 字符串返回给前端。
1
2
3
4
5
6
7
8
9
10// 后端返回JSON响应示例(Spring MVC)
public class UserController {
public User getUser( { Long id)
// 从数据库获取用户
return userService.getUserById(id); // 自动序列化为JSON
}
}服务间通信
在微服务架构中,各个服务之间通过 RESTful API 进行通信,JSON 是最常用的数据格式。像 Spring Cloud 这样的框架,默认就支持 JSON 格式的数据传输。
1
2
3
4// 使用RestTemplate消费REST API
RestTemplate restTemplate = new RestTemplate();
String url = "http://user-service/api/users/{id}";
User user = restTemplate.getForObject(url, User.class, 1L);配置文件的标准选择
尽管,Spring的配置文件标准是xml,yaml和properties(其实也可以支持),但是还是有很多 Java 框架和工具都采用 JSON 作为配置文件的格式,比如:
- Elasticsearch:使用 JSON 来定义索引结构和查询条件。
1
2
3
4
5
6
7
8// Elasticsearch查询示例
{
"query": {
"match": {
"title": "Java Programming"
}
}
}NoSQL 的存储格式
像 MongoDB、Elasticsearch 这类 NoSQL 数据库,直接以 JSON(BSON)格式存储数据,这与 Java 对象的映射非常自然。Redis 等缓存系统也常以 JSON 格式存储复杂对象,这样可以避免频繁查询数据库
日志与监控
JSON 格式在日志记录和监控系统中应用广泛,因为它便于机器解析和分析。
1
2
3
4
5
6
7
8// 使用Logback生成JSON日志
{
"timestamp": "2023-06-15T10:30:00",
"level": "INFO",
"message": "User logged in",
"user": "Alice",
"duration": 123
}
Spring 开发中 JSON 的地位
在现代 Spring 开发中,JSON 已成为数据交互的核心标准,深度融入 Spring 生态系统的各个层面。
在 Spring MVC 的自动序列化中,Spring 通过
@RestController
和 @ResponseBody
自动将 Java
对象序列化为 JSON:
Spring 框架的默认 JSON 处理是 Jackson,当然可以改成 GSON 等
1 |
|
而请求参数绑定中,直接将 JSON 请求体映射到 Java 对象,结合
@Valid
注解和 Bean Validation 进行 JSON 数据校验。
1 |
|
在响应式架构中,JSON 作为数据流的载体:
1 |
|
现代前端框架(React、Vue.js)与 Spring 后端通过 JSON 进行数据交互:
1 | // React 组件调用 Spring API |
Spring 集成 GraphQL 后,JSON 也会成为查询和响应的标准格式
各种外部配置也是支持 JSON 的
1 | // config.json |
而且,Spring Security 集成 JWT,使用 JSON 格式传递身份信息:
1 | { |
还有跨域请求,消息队列,MonogoDB等,也都是用到了 JSON,从其中的共同特点我们可以理解到
JSON 主要用于数据传输
这一点不要忘记
JSON在java中的使用和一些操作
Java中并没有内置JSON的解析,因此使用JSON需要借助第三方类库。
使用JSON官方提供的JSON
官方提供的JSON具有通用性,但是性能不好
1 | <dependency> |
生成 JSON 对象
JSONObject是一个在Java中表示JSON对象的类,通常是由像org.json
,
Gson
,
Jackson
或其他处理JSON的库提供。以org.json
库为例,JSONObject
是一个封装了JSON数据的键值映射的类。这个类允许你创建新的JSON对象、从字符串解析JSON数据以及像操作普通Java对象一样访问或修改JSON对象中的数据。
- 创建JSON对象: 使用 new
来创建一个空的
JSONObject
,或者通过传递一个JSON字符串来构造一个已填充的JSONObject
。 - 添加键值对:
使用
put
方法可以添加键值对,如果键已经存在,将替换键对应的值。 - 获取数据:
提供了
get
和opt
系列方法来获取键对应的值。get
方法在键不存在时会抛出异常,而opt
方法在找不到键时会返回一个默认值(例如null
)或指定的默认值。 - 转换为字符串:
toString()
方法将JSONObject
转换成JSON格式的字符串。 - 检查键:
has
方法可以检查JSONObject
是否包含特定的键。
使用 JSONObject
添加对象是一种常见的创建 JSON
数据的方式。JSONObject
类提供了丰富的方法来操作 JSON
对象。下面是一个示例代码,展示了如何创建一个 JSON
对象并向其中添加不同类型的数据:
1 |
|
在字符串输出的时候会发现,输出的字符串与数据存储的顺序可能是不一致的。原因是调用jsonObject.put()
方法的时候,其底层是一个
HashMap
,数据被存到了HashMap
中。
HashMap
根据键的哈希码来决定键的位置,所以可能会出现上面的问题。
既然 jsonObject.put()
方法的底层是对 HashMap
的操作,那么能否将一个 HashMap
转换成 JSON
数据呢?答案是可以的。原因是 JSONObject
类提供了一个构造函数,这个构造函数中接收的正是一个
Map
。以下是一个将 HashMap
转换为
JSONObject
的示例代码:
1 | import org.json.JSONObject; |

生成JSONArray数组类
JSONArray
是Java中用于表示JSON数组的类,类似于JSONObject
,它是用来处理JSON数据中的数组类型。JSON数组是一个有序的元素集合,每个元素可以是任意类型,如字符串、数字、JSON对象、其他数组等。这个类提供了一系列的方法来创建、解析和操作JSON数组。
- 添加元素: 使用
put
方法来向数组中添加元素。 - 提取元素: 可以通过索引来取数组中的元素,使用诸如
getString(index)
,getJSONObject(index)
等方法。 - 修改元素: 可以通过传递索引和新值到
put
方法来修改数组中的元素。 - 数组长度: 使用
length
方法可以获取数组的长度。 - 遍历数组:
对
JSONArray
进行遍历,通常使用for
循环结合get
方法访问每个元素。 - 转换为字符串:
toString
方法可以将整个数组转换成JSON格式的字符串。
1 | import org.json.JSONArray; |
JavaBean 转 json
1 | public class User { |
JavaBean To JSON
1 | public static void beanToJsonTest() { |
解析JSON
除了生成 JSON 数据,我们还经常需要解析 JSON
数据。JSONObject
类提供了一系列方法来获取 JSON
对象中的数据。以下是一个解析 JSON 字符串的示例代码:
1 | import org.json.JSONArray; |
我们首先定义了一个 JSON 字符串,然后使用 JSONObject
的构造函数将其解析为 JSONObject
对象。接着,我们使用
getString
、getInt
、getBoolean
等方法获取 JSON 对象中的数据。对于 JSON 数组,我们使用
getJSONArray
方法获取,并通过循环遍历数组中的元素。
虽然官方的 JSON 库具有通用性,但由于其底层使用 HashMap
存储数据,可能会导致输出顺序与存储顺序不一致的问题。同时,该库的性能相对较差,在处理大量数据时可能会有性能瓶颈。在实际开发中,可以根据具体需求选择合适的
JSON 处理库,如 Jackson、Gson 等,它们在性能和功能上都有更好的表现。
使用 GSON
GSON 是由 Google 开发的库,能简便地实现 Java 对象和 JSON 数据间的相互转换。
我更推荐大家在做开发的时候使用 GSON,感觉简单好学还不难写
导入依赖
1 | <dependency> |
Java 对象转 JSON (序列化)
借助Gson.toJson()
方法,把 Java 对象序列化为 JSON
字符串。
1 | import com.google.gson.Gson; |
JSON 转 Java 对象(反序列化)
利用Gson.fromJson()
方法,可以将 JSON 字符串反序列化为
Java 对象。
1 | String json = "{\"name\":\"Bob\",\"age\":25,\"hobbies\":[\"Running\",\"Cooking\"]}"; |
使用 FastJSON
FastJSON是阿里巴巴的产品,效率最高
序列化和反序列化等使用操作不介绍了,因为我没用过
Spring默认使用的JSON工具–Jackson
二遍:讲的东西不够多,不够细,应该单开一篇
Jackson 是处理 JSON 数据的顶尖库,它以高性能、丰富功能和广泛的社区支持闻名。
Spring 一系列框架的JSON处理就是默认使用的 JackSon,JackSon是Spring的御用工具,和Spring无缝集成,提供灵活的定制化开发的注解。如果使用Spring框架进行开发,建议使用JackSon。
Jackson包含两个不同的解析器:
- Jackson ObjectMapper,将JSON转化为Java对象,或者转换为Jackson特定的树结构
- Jackson JsonParser,JSON流解析器,每次只解析一个JSON标记
Jackson还包含两个不同的生成器:
- Jackson ObjectMapper,可以从Java对象生成JSON,或者是从Jackson的树结构生成JSON
- Jackson Generator,每次生成一个JSON标记
若使用 Maven 项目,在 pom.xml
文件中添加如下依赖
1 | <dependency> |
Java 对象与 JSON 的转换:核心类
ObjectMapper
可实现 Java 对象与 JSON 的相互转换
ObjectMapper
解析JSON的原理:
默认情况下,Jackson 通过 Java bean 的 get,set 方法,通过去掉 get,set 再把首字母小写得到的名字去和 JSON 的属性进行匹配。
例如对于 getBrand()
和
setBrand()
经过处理得到 brand
,就会匹配到 JSON
的brand
属性,从而把JSON brand
属性的值赋给bean
的brand
字段。通过一系列这样的处理,就将
JSON 转换成了 Java
bean。如果需要以不同的方式来匹配,那么就得使用定制的serializer
和deserializer
,或者使用Jackson提供的众多的注解。
而配置ObjectMapper的工作方式也就是反序列化并不是完全直接反着来的:
有时JSON会拥有比Java对象更多的属性,这种情况下Jackson默认会抛出异常,大概意思是说JSON某个属性未知因为在Java bean中未找到该属性。这种情况下,Jackson允许通过配置来忽略未知的属性
1 | import com.fasterxml.jackson.databind.ObjectMapper; |
Jackson 提供了丰富的注解,用于精确控制序列化和反序列化过程:
1 | public class User { |
对于大型 JSON 文件,使用 JsonParser
和
JsonGenerator
进行高效处理:
1 | // 写入JSON |