1. 概述

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,最常用于客户端与服务器之间的通信。它既易于读写,又独立于编程语言。JSON 值可以是另一个 JSON 对象、数组、数字、字符串、布尔值(true/false)或 null。

本教程将介绍如何使用 Java 中可用的 JSON 处理库之一——JSON-Java 库(也称为 org.json)来创建、操作和解析 JSON。

2. 前置准备

首先,在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20250517</version>
</dependency>

最新版本可在 Maven 中央仓库 获取。

⚠️ 注意:使用 Android SDK 时无需显式添加此依赖,因为 Android 已内置该包。

3. Java 中的 JSON 处理 [org.json 包]

我们使用 JSON-Java 库中的类来解析和操作 JSON。该库也称为 org.json切勿与 Google 的 org.json.simple 库混淆

此外,该库还支持 JSON 与 XML、HTTP 头、Cookie、逗号分隔列表或文本等格式之间的转换。

本教程将重点介绍以下核心类:

  1. JSONObject:类似 Java 原生 Map 的对象,存储无序的键值对
  2. JSONArray:类似 Java 原生 Vector 的有序值序列
  3. JSONTokener:将文本分解为一系列标记(token)的工具,供 JSONObject 或 JSONArray 解析 JSON 字符串
  4. CDL:提供逗号分隔文本与 JSONArray 相互转换的方法
  5. Cookie:JSON 字符串与 Cookie 相互转换
  6. HTTP:JSON 字符串与 HTTP 头相互转换
  7. JSONException:库抛出的标准异常

4. JSONObject

JSONObject 是键值对的无序集合,类似 Java 原生 Map 实现:

  • 键是唯一的非空 String
  • 值可以是 Boolean、Number、String、JSONArray 甚至 JSONObject.NULL 对象
  • JSONObject 可表示为花括号包裹的字符串,键值对用冒号分隔,元素间用逗号分隔
  • 提供多种构造方法创建 JSONObject

主要方法包括:

  1. *get(String key)*:获取指定键关联的对象,键不存在时抛出 JSONException
  2. *opt(String key)*:获取指定键关联的对象,键不存在时返回 null
  3. *put(String key, Object value)*:插入或替换当前 JSONObject 中的键值对

put() 方法已重载,支持多种值类型。完整方法列表见官方文档

4.1. 直接通过 JSONObject 创建 JSON

JSONObject 暴露了类似 Java Map 接口的 API。使用 put() 方法传入键值对:

JSONObject jo = new JSONObject();
jo.put("name", "jon doe");
jo.put("age", "22");
jo.put("city", "chicago");

生成的 JSONObject 如下:

{"city":"chicago","name":"jon doe","age":"22"}

JSONObject.put() 提供七种重载签名。键必须是唯一非空 String,值类型不限。

4.2. 从 Map 创建 JSON

也可先构建自定义 Map,再作为参数传给 JSONObject 构造方法:

Map<String, String> map = new HashMap<>();
map.put("name", "jon doe");
map.put("age", "22");
map.put("city", "chicago");
JSONObject jo = new JSONObject(map);

结果与 4.1 节相同。

4.3. 从 JSON String 创建 JSONObject

将 JSON 字符串传给构造方法即可解析(注意转义双引号):

JSONObject jo = new JSONObject(
  "{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"
);

⚠️ 传入的字符串必须是有效 JSON,否则构造方法会抛出 JSONException。

4.4. 从 JSON 字符串解析值

构建 JSONObject 实例后,使用对应的 get 方法获取属性值。对于嵌套的 JSON 属性,可递归获取:

@Test
void givenJSON_whenParsed_thenCorrectValueReturned() {
    String jsonString = """
                        {
                            "type": "Feature", 
                            "geometry": "Point",
                            "properties": {
                                              "isValid": true, 
                                              "name": "Sample Point"
                                          }
                        }
                        """;
    JSONObject jsonObject = new JSONObject(jsonString);
    String type = jsonObject.getString("type");
    String geometry = jsonObject.getString("geometry");
    JSONObject properties = jsonObject.getJSONObject("properties");
    boolean isValid = properties.getBoolean("isValid");
    assertEquals(type,"Feature");
    assertEquals(geometry,"Point");
    assertTrue(isValid);
}

4.5. 序列化 Java 对象为 JSON

JSONObject 的构造方法可接受 POJO 作为参数。库会使用 DemoBean 类的 getter 创建对应的 JSONObject:

DemoBean demo = new DemoBean();
demo.setId(1);
demo.setName("lorem ipsum");
demo.setActive(true);

JSONObject jo = new JSONObject(demo);

生成的 JSONObject:

{
    "name":"lorem ipsum",
    "active":true,
    "id":1
}

✅ 虽然支持 Java 对象转 JSON,但该库不支持反向转换。如需双向转换,建议使用 Jackson 等库。

5. JSONArray

JSONArray 是值的有序集合,类似 Java 原生 Vector 实现:

  • 值可以是 Number、String、Boolean、JSONArray、JSONObject 甚至 JSONObject.NULL
  • 表示为方括号包裹的字符串,值间用逗号分隔
  • 构造方法接受源字符串并解析为 JSONArray

主要方法包括:

  1. *get(int index)*:返回指定索引(0 到 length-1)的值,越界抛出 JSONException
  2. *opt(int index)*:返回指定索引的值,越界返回 null
  3. *put(Object value)*:向 JSONArray 末尾追加值(已重载支持多种数据类型)

完整方法列表见官方文档

5.1. 创建 JSONArray

初始化 JSONArray 后,使用 put()get() 添加/获取元素:

JSONArray ja = new JSONArray();
ja.put(Boolean.TRUE);
ja.put("lorem ipsum");

JSONObject jo = new JSONObject();
jo.put("name", "jon doe");
jo.put("age", "22");
jo.put("city", "chicago");

ja.put(jo);

生成的 JSONArray(格式化后):

[
    true,
    "lorem ipsum",
    {
        "city": "chicago",
        "name": "jon doe",
        "age": "22"
    }
]

5.2. 直接从 JSON 字符串创建 JSONArray

构造方法支持直接解析 JSON 字符串:

JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]");

⚠️ 若字符串不是有效 JSON,构造方法会抛出 JSONException。

5.3. 从集合或数组创建 JSONArray

构造方法支持 Collection 或数组作为参数:

List<String> list = new ArrayList<>();
list.add("California");
list.add("Texas");
list.add("Hawaii");
list.add("Alaska");

JSONArray ja = new JSONArray(list);

生成的 JSONArray:

["California","Texas","Hawaii","Alaska"]

5.4. 从 JSONArray 移除元素

使用 remove(int index) 移除特定元素。继续使用州名示例,移除 "Alaska":

ja.remove(3);

输出剩余元素:

System.out.println(ja.toString());
// ["California","Texas","Hawaii"]

remove(int index) 返回被移除的元素:

Object removed = ja.remove(3);
System.out.println(removed); // Alaska

⚠️ 移除元素后 JSONArray 长度减 1。索引从 0 开始,尝试移除不存在的索引(如 *ja.remove(4)*)不会抛异常,需自行验证。

6. JSONTokener

JSONTokener 接受源字符串并从中提取字符和标记。该库内部类(如 JSONObject、JSONArray)使用它解析 JSON 字符串。

直接使用场景较少,因其他方法(如 *string.toCharArray()*)可替代:

JSONTokener jt = new JSONTokener("lorem");

while(jt.more()) {
    Log.info(jt.next());
}

输出标记:

l
o
r
e
m

7. CDL

CDL(逗号分隔列表)提供逗号分隔文本与 JSONArray 的相互转换。

7.1. 从逗号分隔文本生成 JSONArray

使用静态方法 *rowToJSONArray()*,接受 JSONTokener 参数:

JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada"));

生成的 JSONArray:

["England","USA","Canada"]

7.2. 从 JSONArray 生成逗号分隔文本

反向操作:

JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]");
String cdt = CDL.rowToString(ja);

生成的字符串:

England,USA,Canada

7.3. 使用逗号分隔文本生成 JSONObject 数组

文本需同时包含表头和数据,用回车(\r)或换行(\n)分隔。首行为表头,后续行为数据:

String string = "name, city, age \n" +
  "john, chicago, 22 \n" +
  "gary, florida, 35 \n" +
  "sal, vegas, 18";

JSONArray result = CDL.toJSONArray(string);

生成的 JSONArray(格式化后):

[
    {
        "name": "john",
        "city": "chicago",
        "age": "22"
    },
    {
        "name": "gary",
        "city": "florida",
        "age": "35"
    },
    {
        "name": "sal",
        "city": "vegas",
        "age": "18"
    }
]

✅ 替代方案:单独提供表头 JSONArray 和数据字符串:

JSONArray ja = new JSONArray();
ja.put("name");
ja.put("city");
ja.put("age");

String string = "john, chicago, 22 \n"
  + "gary, florida, 35 \n"
  + "sal, vegas, 18";

JSONArray result = CDL.toJSONArray(ja, string);

结果与之前相同。

Cookie 类处理浏览器 Cookie,提供 Cookie 字符串与 JSONObject 的相互转换。

主要方法:

  1. *toJsonObject(String sourceCookie)*:将 Cookie 字符串转为 JSONObject
  2. *toString(JSONObject jo)*:将 JSONObject 转为 Cookie 字符串
String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
JSONObject cookieJO = Cookie.toJSONObject(cookie);
String cookie = Cookie.toString(cookieJO);

9. HTTP

HTTP 类提供 HTTP 头与 JSONObject 的相互转换。

主要方法:

  1. *toJsonObject(String sourceHttpHeader)*:HTTP 头字符串转 JSONObject
  2. *toString(JSONObject jo)*:JSONObject 转 HTTP 头字符串

9.1. JSONObject 转 HTTP 头

JSONObject jo = new JSONObject();
jo.put("Method", "POST");
jo.put("Request-URI", "http://www.example.com/");
jo.put("HTTP-Version", "HTTP/1.1");
String httpStr = HTTP.toString(jo);

生成的 HTTP 头:

POST "http://www.example.com/" HTTP/1.1

⚠️ 转换请求头时 JSONObject 必须包含 "Method"、"Request-URI" 和 "HTTP-Version" 键;响应头需包含 "HTTP-Version"、"Status-Code" 和 "Reason-Phrase"。

9.2. HTTP 头字符串转 JSONObject

JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1");

10. JSONException

JSONException 是库抛出的标准异常,包含错误详情信息。该库所有类均使用此异常。

11. 解析 JSON 布尔值

org.json.JSONObject 是 Java 中解析 JSON 布尔值最常用的类。

11.1. 解析 truefalse

从 JSON 字符串创建 JSONObject,使用 getBoolean(String) 获取布尔属性:

@Test
void givenJSONString_whenParsed_thenCorrectBooleanValueReturned() {
    String json = """
                  { 
                      "name": "lorem ipsum",
                      "active": true,
                      "id": 1
                  }
                  """;
    JSONObject jsonObject = new JSONObject(jsonString);
    boolean active = jsonObject.getBoolean("active");
    assertTrue(active);
}

11.2. 解析 01

某些系统用 0/1 表示布尔值。获取整数值后用 AssertJ 验证:

@Test
void givenJSONWithBooleanAs0Or1_whenParsed_correctBooleanValueReturned() {
    String json = """
                  { 
                      "name": "lorem ipsum",
                      "active": 1,
                      "id": 1
                  }
                  """;
    JSONObject jsonObject = new JSONObject(json);
    assertThat(jsonObject.getInt("active")).isEqualTo(1);
}

11.3. 解析混合布尔表示

当不确定布尔值是 true/false 还是 0/1 时:

@Test
void givenJSONWithMixedRepresentationForBoolean_whenParsed_thenCorrectBooleanValueReturned() {
    JSONObject jsonObject = new JSONObject(json);
    Object activeObject = jsonObject.get("active");
    if (activeObject instanceof Integer value) {
        assertTrue(value == 1);
    } else if (activeObject instanceof Boolean value) {
        assertTrue(value);
      }  
}

12. 总结

本文介绍了 Java 的 JSON 处理库——org.json,重点展示了其核心功能。该库简单粗暴,适合基础 JSON 操作,但复杂场景建议搭配 Jackson/Gson 等库使用。


原始标题:Introduction to JSON-Java | Baeldung