1. 概述

本文将介绍两种将 BufferedReader 转换为 JSONObject 的方法,适用于使用 org.json 库处理流式 JSON 数据的场景。

实际开发中,我们常从网络、文件或 API 响应中读取 JSON 数据,输入流通常封装为 BufferedReader。如何高效、安全地将其转为 JSONObject 是个高频需求。下面两种方式,一个简洁,一个兼容性强,看你的 Java 环境和依赖版本怎么选。

2. 依赖配置

使用 org.json 库前,先在 pom.xml 中引入依赖:

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

✅ 推荐使用较新版本(如 20240303),支持直接从 Reader 构造 JSON,避免中间转换。

3. 使用 JSONTokener(推荐方式)

org.json 的新版本提供了一个非常实用的类:JSONTokener,它的构造函数直接接受 Reader 类型参数,这意味着你可以把 BufferedReader 原样传进去,无需转成字符串。

✅ 这种方式内存友好、代码简洁,是当前最推荐的做法。

示例代码如下:

@Test
public void givenValidJson_whenUsingBufferedReader_thenJSONTokenerConverts() {
    byte[] b = "{ \"name\" : \"John\", \"age\" : 18 }".getBytes(StandardCharsets.UTF_8);
    InputStream is = new ByteArrayInputStream(b);
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
    JSONTokener tokener = new JSONTokener(bufferedReader);
    JSONObject json = new JSONObject(tokener);

    assertNotNull(json);
    assertEquals("John", json.get("name"));
    assertEquals(18, json.get("age"));
}

⚠️ 注意:JSONTokener 会消费流(即读取并关闭),确保流的生命周期可控,避免后续重复读取失败。

4. 先转换为 String(兼容旧版本)

如果你的项目还在用老版本的 org.json(比如 < 2023 版本),不支持 JSONTokener(Reader),那就得先将 BufferedReader 读成字符串,再用字符串构造 JSONObject

虽然多了一步,但胜在兼容性好,属于“踩坑”后常见的 fallback 方案。

实现方式也很简单:

@Test
public void givenValidJson_whenUsingString_thenJSONObjectConverts()
  throws IOException {
    byte[] b = "{ \"name\" : \"John\", \"age\" : 18 }".getBytes(StandardCharsets.UTF_8);
    InputStream is = new ByteArrayInputStream(b);
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));

    StringBuilder sb = new StringBuilder();
    String line;
    while ((line = bufferedReader.readLine()) != null) {
        sb.append(line);
    }
    
    JSONObject json = new JSONObject(sb.toString());

    assertNotNull(json);
    assertEquals("John", json.get("name"));
    assertEquals(18, json.get("age"));

    bufferedReader.close();
}

❌ 踩坑提醒:

  • 多次 readLine() 拼接时,别忘了处理换行符。如果原始 JSON 被分行读取,直接拼接可能导致语法错误。建议使用 sb.append(line).append("\n") 或统一去除换行。
  • 大文件场景下,StringBuilder 可能引发内存溢出,慎用。

5. 总结

方法 优点 缺点 适用场景
JSONTokener(bufferedReader) 代码简洁、内存友好、无需中间字符串 需要较新版本 org.json 推荐新项目使用
✅ 先转 String 再构造 兼容老版本库 内存占用高、有性能开销 老系统维护、无法升级依赖时

📌 结论:优先使用 JSONTokener 方式,简单粗暴又高效。只有在受限于旧版本时,才退而求其次转成字符串。

完整示例代码已托管至 GitHub: 👉 https://github.com/baeldung/tutorials/tree/master/core-java-modules/core-java-io-conversions-2


原始标题:Converting a BufferedReader to a JSONObject | Baeldung