On Mon, 10 Aug 2026 17:36:35 GMT, Naoto Sato <[email protected]> wrote:

> This PR implements [JEP 540: Simple JSON API 
> (Incubator)](https://openjdk.org/jeps/540).
> 
> It adds the `jdk.incubator.json` module which provides APIs for reading and 
> writing JSON documents as specified by [RFC 
> 8259](https://datatracker.ietf.org/doc/html/rfc8259). This is an incubating 
> API.
> 
> API documentation: 
> https://cr.openjdk.org/~naoto/json/javadoc/api/jdk.incubator.json/module-summary.html
> Co-authored-by: Justin Lu 
> ([@justin-curtis-lu](https://github.com/justin-curtis-lu))
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

src/jdk.incubator.json/share/classes/jdk/incubator/json/impl/JsonParser.java 
line 62:

> 60: 
> 61:     // Parses the lone JsonValue root
> 62:     public JsonValue parseRoot() {

Maybe also add a strongly typed overload so that the likes of 
`JsonNumber​::of(String)` can abort parsing early if the `String` is actually a 
very large non‑`JsonNumber` value, like a `JsonObject` or `JsonArray`[^1], such 
as:

public <T extends JsonValue> T parseTypedRoot(Class<T> type) {
        assert VALID_TYPE_ARGS.containsKey(type) : type;
        JsonValue root = parseTypedValue(type);
        if (hasInput()) {
                throw valueFailure(0, "Additional value(s) were found after the 
JSON Value");
        }
        return root;
}

private JsonValue parseValue() {
        return parseTypedValue(JsonValue.class);
}

private static final Map<Class<? extends JsonValue>, String> VALID_TYPE_ARGS = 
Map.of(
        JsonValue.class,        "JSON Object, Array, String, Number, Boolean, 
or Null",
        JsonObject.class,       "JSON Object",
        JsonArray.class,        "JSON Array",
        JsonString.class,       "JSON String",
        JsonNumber.class,       "JSON Number",
        JsonBoolean.class,      "JSON Boolean",
        JsonNull.class,         "JSON Null",
);

private <T extends JsonValue> T parseTypedValue(Class<T> type) {
        skipWhitespaces();
        var pathStart = offset;
        if (!hasInput()) {
                throw valueFailure(pathStart, "Expected a 
".concat(VALID_TYPE_ARGS.get(type)));
        }
        var val = switch (doc[offset]) {
                case '{' when type.isAssignableFrom(JsonObject.class)   -> 
parseObject();
                case '[' when type.isAssignableFrom(JsonArray.class)    -> 
parseArray();
                case '"' when type.isAssignableFrom(JsonString.class)   -> 
parseString();
                case 't' when type.isAssignableFrom(JsonBoolean.class)  -> 
parseTrue();
                case 'f' when type.isAssignableFrom(JsonBoolean.class)  -> 
parseFalse();
                case 'n' when type.isAssignableFrom(JsonNull.class)     -> 
parseNull();
                // While JSON Number does not support leading '+', '.', or 'e'
                // we still accept, so that we can provide a better error 
message
                case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', 
'+', 'e', '.'
                                when type.isAssignableFrom(JsonNumber.class) -> 
parseNumber();
                default -> throw valueFailure(pathStart, "Unexpected value. 
Expected a "
                                .concat(VALID_TYPE_ARGS.get(type)));
        };
        // Attribute incorrect values appended directly on a valid value as
        // error on the value rather than its enclosing structure.
        if (hasInput()) {
                switch (doc[offset]) {
                        case ']', '}', ',', ' ', '\t','\r', '\n' -> {}
                        default -> throw valueFailure(pathStart, "Unexpected 
content after JSON value");
                }
        }
        skipWhitespaces();
        return val;
}


[^1]: Which would force the allocation of a large number of implementation 
instances.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/32282#discussion_r3774867275

Reply via email to