杰瑞科技汇

JsonObject与Java对象如何转换?

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

JsonObject与Java对象如何转换?-图1
(图片来源网络,侵删)

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 处理库,最常用和最流行的库是:

JsonObject与Java对象如何转换?-图2
(图片来源网络,侵删)
  1. org.json: 这是一个非常轻量级、简单易用的库,它提供了 JSONObject, JSONArray, JSONStringer 等核心类,很多 Android 开发和轻量级项目会使用它。
  2. com.google.gson: Google 出品,功能强大,性能优秀,API 设计优雅,它不仅能处理 JSONObject,还能轻松地在 Java 对象和 JSON 字符串之间进行转换。
  3. 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与Java对象如何转换?-图3
(图片来源网络,侵删)

直接构建一个空的 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 之间的转换,强烈推荐使用 GsonJackson,它们提供了更优雅、更强大的自动转换功能。

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 就足够了。

分享:
扫描分享到社交APP
上一篇
下一篇