JSONObject 是一个非常核心和常用的 Java 类,它主要用于表示和操作 JSON(JavaScript Object Notation)格式的数据,JSON 是一种轻量级的数据交换格式,因其易于人阅读和编写,也易于机器解析和生成,因此在 Web 开发(特别是前后端交互)中得到了广泛应用。

JSONObject 是什么?
JSONObject 本质上是一个 键值对的集合,类似于 Java 中的 Map<String, Object>,它由一系列“键”(Key)和“值”(Value)对组成,用花括号 包裹,键必须是字符串,而值可以是多种类型,如字符串、数字、布尔值、数组、另一个 JSONObject,甚至是 null。
一个典型的 JSON 对象长这样:
{
"name": "张三",
"age": 30,
"isStudent": false,
"courses": ["数学", "物理"],
"address": {
"city": "北京",
"district": "海淀区"
},
"phone": null
}
在 Java 中,这个 JSON 对象就可以用一个 JSONObject 来表示。
JSONObject 的来源(库)
Java 标准库中并没有直接包含 JSONObject 类,它通常来自第三方 JSON 处理库,最常用和最流行的库是:

org.json: 这是一个非常轻量级、简单易用的库,它提供了JSONObject,JSONArray,JSONStringer等核心类,很多 Android 开发和轻量级项目会使用它。com.google.gson: Google 出品,功能强大,性能优秀,API 设计优雅,它不仅能处理JSONObject,还能轻松地在 Java 对象和 JSON 字符串之间进行转换。com.fasterxml.jackson.databind: Jackson 是目前 Java 生态中最流行、功能最全面的 JSON 库,它在处理大型 JSON 数据、复杂对象映射、流式处理等方面表现出色,是 Spring Boot 等框架的默认选择。
本文将以最经典的 org.json 库为例进行讲解,因为它最能体现 JSONObject 的基本用法,其他库的 JSONObject 概念相似,但 API 会略有不同。
如何使用 org.json 库?
1 添加依赖
如果你使用 Maven,在 pom.xml 中添加:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20251013</version> <!-- 使用最新的稳定版本 -->
</dependency>
如果你使用 Gradle,在 build.gradle 中添加:
implementation 'org.json:json:20251013' // 使用最新的稳定版本
2 创建 JSONObject
创建 JSONObject 有多种方式:

直接构建一个空的 JSONObject
import org.json.JSONObject; JSONObject jsonObj = new JSONObject();
从 JSON 格式的字符串创建
这是最常见的用法,通常用于解析从服务器接收到的 JSON 响应。
String jsonString = "{\"name\":\"张三\",\"age\":30}";
JSONObject jsonObj = new JSONObject(jsonString);
System.out.println(jsonObj); // 输出: {"name":"张三","age":30}
使用 put 方法动态添加键值对
JSONObject jsonObj = new JSONObject();
jsonObj.put("name", "李四");
jsonObj.put("age", 25);
jsonObj.put("isStudent", true);
jsonObj.put("courses", new JSONArray().put("化学").put("生物"));
System.out.println(jsonObj.toString());
// 输出: {"name":"李四","age":25,"isStudent":true,"courses":["化学","生物"]}
3 从 JSONObject 中获取数据
使用 get() 或其类型化的便捷方法(如 getString(), getInt())来获取值。
String jsonString = "{\"name\":\"王五\",\"age\":28,\"city\":\"上海\"}";
JSONObject jsonObj = new JSONObject(jsonString);
// 使用 get() 方法 (需要类型转换)
String name = (String) jsonObj.get("name");
int age = jsonObj.getInt("age"); // getInt() 是便捷方法,无需转换
String city = jsonObj.getString("city");
System.out.println("姓名: " + name); // 输出: 姓名: 王五
System.out.println("年龄: " + age); // 输出: 年龄: 28
System.out.println("城市: " + city); // 输出: 城市: 上海
重要:如果键不存在,get() 方法会抛出 JSONException,为了避免异常,可以使用 opt() 系列方法。
opt() 方法在键不存在时会返回 null 或一个默认值,而不会抛出异常。
// 使用 opt() 方法,更安全
String country = jsonObj.optString("country", "中国"); // "country" 不存在,返回默认值 "中国"
System.out.println("国家: " + country); // 输出: 国家: 中国
Boolean isMarried = jsonObj.optBoolean("isMarried"); // "isMarried" 不存在,返回 false
System.out.println("已婚: " + isMarried); // 输出: 已婚: false
4 嵌套 JSON 对象的处理
JSON 对象的值可以是另一个 JSONObject,我们可以通过递归或链式调用来访问它。
String nestedJson = "{\"user\":{\"name\":\"赵六\",\"contact\":{\"email\":\"zhaoliu@example.com\"}}}";
JSONObject jsonObj = new JSONObject(nestedJson);
// 获取嵌套的 user 对象
JSONObject userObj = jsonObj.getJSONObject("user");
String userName = userObj.getString("name");
// 链式调用获取更深层的 email
String email = jsonObj.getJSONObject("user").getJSONObject("contact").getString("email");
System.out.println("用户名: " + userName); // 输出: 用户名: 赵六
System.out.println("邮箱: " + email); // 输出: 邮箱: zhaoliu@example.com
5 遍历 JSONObject
如果你想遍历 JSONObject 中的所有键值对,可以使用 keys() 方法获取键的迭代器。
String jsonString = "{\"k1\":\"v1\",\"k2\":123,\"k3\":true}";
JSONObject jsonObj = new JSONObject(jsonString);
System.out.println("遍历 JSONObject:");
for (String key : jsonObj.keySet()) {
Object value = jsonObj.get(key);
System.out.println("键: " + key + ", 值: " + value + ", 类型: " + value.getClass().getSimpleName());
}
输出:
遍历 JSONObject:
键: k1, 值: v1, 类型: String
键: k2, 值: 123, 类型: Integer
键: k3, 值: true, 类型: Boolean
JSONObject 与 Java POJO(普通 Java 对象)的转换
在实际开发中,我们更希望将 JSON 数据直接映射到 Java 对象,而不是手动操作 JSONObject,这能提供更好的类型安全和代码可读性。
使用 org.json 库进行转换:
定义一个 Java 类(POJO)
public class User {
private String name;
private int age;
private String email;
// 必须有无参构造函数
public User() {}
// 建议有 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; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", age=" + age + ", email='" + email + '\'' + '}';
}
}
从 JSONObject 转换为 Java 对象
String jsonStr = "{\"name\":\"钱七\",\"age\":32,\"email\":\"qianqi@example.com\"}";
JSONObject jsonObj = new JSONObject(jsonStr);
User user = new User();
user.setName(jsonObj.getString("name"));
user.setAge(jsonObj.getInt("age"));
user.setEmail(jsonObj.getString("email"));
System.out.println(user); // 输出: User{name='钱七', age=32, email='qianqi@example.com'}
这种方式比较繁琐,需要手动为每个字段赋值。
从 Java 对象转换为 JSONObject
User user = new User();
user.setName("孙八");
user.setAge(40);
user.setEmail("sunba@example.com");
// 使用 JSONObject 的构造函数,传入一个 Map
// 或者使用 JavaBean 的转换器(org.json 提供了辅助类,但不如 Gson/Jackson 方便)
JSONObject userJson = new JSONObject(user.toString()); // 这不是最佳实践,只是演示
// 更好的方式是手动构建
JSONObject userJsonManual = new JSONObject();
userJsonManual.put("name", user.getName());
userJsonManual.put("age", user.getAge());
userJsonManual.put("email", user.getEmail());
System.out.println(userJsonManual.toString());
// 输出: {"name":"孙八","age":40,"email":"sunba@example.com"}
org.json 库非常适合处理简单的 JSON 数据,但如果需要进行复杂的 Java 对象和 JSON 之间的转换,强烈推荐使用 Gson 或 Jackson,它们提供了更优雅、更强大的自动转换功能。
JSONObject vs. Map<String, Object>
| 特性 | JSONObject |
Map<String, Object> |
|---|---|---|
| 类型 | 专门用于 JSON 处理的类 | Java 标准集合框架 |
| API | 提供 put(), get(), opt(), toString() 等专门针对 JSON 的方法 |
提供 put(), get() 等 Map 通用方法 |
| 序列化 | toString() 方法直接生成 JSON 字符串,非常方便 |
需要手动迭代 Map 并拼接字符串,或使用第三方库(如 Jackson)进行序列化 |
| 反序列化 | 构造函数可以直接解析 JSON 字符串 | 没有内置的 JSON 解析能力 |
| 可读性 | 代码意图明确,一看就知道是在处理 JSON | 代码意图模糊,可能只是普通的键值存储 |
| 灵活性 | 相对固定,专注于 JSON | 非常灵活,可以存储任何类型的键值对 |
当你的代码明确是在处理 JSON 数据时,使用 JSONObject 能让代码更清晰、更健壮,并且能直接利用其 JSON 特定的功能,如果只是需要一个通用的键值存储,并且不涉及 JSON 的序列化/反序列化,使用 Map 就足够了。
