JEP 540(Simple JSON API)已 Integrated,目标发行版是 JDK 28。它在 jdk.incubator.json 模块里提供严格按 RFC 8259 的解析与生成,树形模型,不开 data binding,也不做 streaming。要用它,编译和运行都得加 --add-modules jdk.incubator.json。inside.java 首页在 2026-10-02 用卡片链到了这篇 JEP,目前没有单独博文页。

JDK 自己不能依赖 Jackson 这类外部库,配置文件和诊断输出却越来越需要结构化数据。540 把「简单读一下 JSON、写一点 JSON」收进平台,复杂绑定和流式处理继续交给既有库。

它能做什么

API 围着密封接口 JsonValue 转,六个子类型对应 RFC 8259 的六种值:JsonString、JsonNumber、JsonBoolean、JsonNull、JsonObject、JsonArray。入口是 Json.parse(String) 或 Json.parse(char[]),成功得到树,失败抛未检查异常 JsonParseException,消息里带路径和行列位置。

导航不用先强转类型。对象用 get(String),数组用 get(int),一路链式走到叶子再转换:

子类型转换方法Java 结果
JsonStringasString()String
JsonNumberasInt() / asLong() / asDouble()对应原始类型(须可精确或准确表示)
JsonBooleanasBoolean()boolean
JsonObjectasMap()不可变 Map
JsonArrayasList()不可变 List

成员可能缺失时用 tryGet,得到 Optional。值可能是 JSON null 时用 tryValue。结构随版本漂移时,可用 switch 加类型模式区分,例如线程转储里 tid 在旧版是字符串、新版是数字。

生成侧,JsonObject.of / JsonArray.of / JsonString.of 等工厂拼出树,toString() 给紧凑串,Json.toDisplayString(value, indent) 给可读缩进。输出都能再被 Json.parse 吃回去。

数字按 RFC 8259 可任意精度。常用路径走 asInt / asLong / asDouble;要无损可 new BigDecimal(jn.toString())。越界或无法精确表示会抛 JsonValueException。

它明确不做的事

JEP 的 Non-Goals 写得很干脆:不打算取代成熟的外部 JSON 库。刻意砍掉的能力包括:

  • Data binding:不把 JSON 自动映射成业务 POJO,也不做注解驱动的序列化定制。
  • Streaming / 事件推送:大文档要边读边处理,仍用 Jackson Streaming、Jakarta JSON-P 等。
  • 语法扩展:不认 trailing comma、注释、JSON5。机器对机器通信优先严格互通。
  • 重复成员名:对象里出现重复 key 直接解析失败。RFC 8259 只说 SHOULD unique,540 选了更严的策略,避免多库共存时「同名成员解析结果不一致」。

文档还假设输入能放进内存(String 或 char[])。超大文件请走流式方案,不要指望这个孵化 API。

和 Jackson、Gson 怎么分工

场景更合适的选择
脚本、小工具、JDK 自用配置、探索陌生 JSONJEP 540(孵化中)
复杂对象图、多态、自定义命名与类型适配Jackson / Gson / Jakarta JSON-B
超大 JSON、边解析边处理Jackson Streaming、JSON-P Streaming
需要注释或宽松语法的人手写配置先预处理,或继续用支持扩展的库

JEP 自己说:应用从平台 API 起步,后来长大需要绑定或流式,迁到外部库不算失败。孵化期 API 还可能改形状,生产关键路径仍以成熟库为主更稳妥。

启用方式与天气 API 示例

模块默认不在解析集里。编译和运行都要打开:

javac --add-modules jdk.incubator.json Weather.java
java --add-modules jdk.incubator.json Weather

单文件源码程序可以一步跑:

java --add-modules jdk.incubator.json Weather.java

下面这段摘自 JEP 附录:请求美国国家气象局的预报 JSON,取出 properties.periods 里各时段温度求平均。完整语义以 JEP 540 为准,本文未在本地 JDK 28 EA 上复跑。

import java.net.*;
import java.net.http.*;
import jdk.incubator.json.Json;
import jdk.incubator.json.JsonValue;

void main() throws Exception {
    var query = "https://api.weather.gov/gridpoints/MTR/97,83/forecast";
    var client = HttpClient.newHttpClient();
    var request = HttpRequest.newBuilder(URI.create(query)).build();
    var response = client.send(request, HttpResponse.BodyHandlers.ofString());
    JsonValue json = Json.parse(response.body());
    json.get("properties").get("periods").asList().stream()
        .mapToInt(j -> j.get("temperature").asInt())
        .average()
        .ifPresent(IO::println);
}

jshell --add-modules jdk.incubator.json 也可以交互试探。运行时会出现 incubator 模块警告,属预期行为。

状态与阅读入口

  • 状态:Integrated,Release 28(OpenJDK JEP 页,更新时间见该页)。
  • 模块:jdk.incubator.json,需 --add-modules。
  • 合规:严格 RFC 8259,禁止重复 key,无注释与 trailing comma。
  • 边界:树模型、内存内文档;无 binding、无 streaming。

建议精读 JEP 540 的 Goals、Non-Goals、Parsing 与 Alternatives。站内已有 JEP 541、JEP 544 等 JDK 28 相关稿,540 补的是「平台自带的轻量 JSON」这一块。

参考链接

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。