Saltar al contenido
NextPatch Blog

JSON en el JDK: el JEP 540 entra en JDK 28 como incubadora

JDK 28 trae jdk.incubator.json para parsear y generar JSON sin dependencias externas. Es una incubadora, se activa con --add-modules y no pretende sustituir a Jackson.

Java 2 min de lectura

El JEP 540, Simple JSON API, está integrado en JDK 28 como módulo de incubadora. Por primera vez puedes leer y escribir JSON con lo que trae el JDK, sin añadir nada al pom.xml. El motivo lo resume el propio JEP: añadir cualquier dependencia externa a una aplicación tiene un coste y añade riesgo.

Es una incubadora, no una preview: el módulo jdk.incubator.json se añade con --add-modules jdk.incubator.json al compilar y al ejecutar, y la API puede cambiar. No es para producción.

Leer JSON

Todo gira alrededor de JsonValue, una interfaz sellada cuyos subtipos son JsonObject, JsonArray, JsonString, JsonNumber, JsonBoolean y JsonNull. Json.parse te da la raíz y desde ahí navegas:

java
// java --add-modules jdk.incubator.json Weather.java
import jdk.incubator.json.*;

void main() {
    JsonValue json = Json.parse("""
        {"properties": {"periods": [{"temperature": 18}, {"temperature": 22}]}}
        """);
    json.get("properties").get("periods").asList().stream()
        .mapToInt(j -> j.get("temperature").asInt())
        .average()
        .ifPresent(IO::println); // 20.0
}

Si un miembro no existe o el tipo no es el que esperas, los métodos de acceso lanzan JsonValueException con la ruta del problema en el mensaje. Para los miembros opcionales está tryGet: thread.tryGet("waitingOn").ifPresent(...) solo actúa si el miembro existe.

Como la jerarquía es sellada, encaja con el switch de patrones. Este ejemplo es del JEP:

java
long tid = switch (thread.get("tid")) {
    case JsonNumber jn -> jn.asLong();
    case JsonString js -> Long.parseLong(js.asString());
    default -> throw new JsonValueException("Unexpected type for \"tid\"");
};

Generar JSON

También del JEP:

java
IO.println(JsonObject.of(Map.of("providers",
                                JsonArray.of(List.of(JsonString.of("SUN"),
                                                     JsonString.of("SunRsaSign"),
                                                     JsonString.of("SunEC"))))));

Imprime {"providers":["SUN","SunRsaSign","SunEC"]}. Para una salida legible existe Json.toDisplayString(json, " ").

Lo que no hace

El JEP es muy claro: no es un objetivo sustituir a las librerías de JSON que ya existen. Deja fuera a propósito:

  • El data binding (JSON a tus clases y al revés): añadiría mucha API y dispararía el coste de mantenerla.
  • Una API de streaming, útil en casos concretos pero complicada para extraer datos sencillos.
  • Variantes como JSON5: solo RFC 8259, y rechaza objetos con nombres de miembro duplicados.

Así que Jackson se queda donde está. Donde el JEP 540 tiene sentido es en scripts, herramientas internas y pruebas rápidas en las que meter una dependencia no compensa. Durante la incubación, el equipo quiere recoger casos de uso de generación y transformación de JSON para hacer evolucionar esa parte de la API: si lo pruebas, es buen momento para dar tu opinión.

Pasa de leerlo a practicarlo.

Un resumen de 45 segundos y un reto de dos minutos al día. La cuenta es gratis y guarda tu XP, tu racha y tus insignias.

Crear cuenta gratis