Currently, JsonObject.of has this signature:

    static JsonObject of(Map<String, ? extends JsonValue> map);
java.lang.String and other types don't extend JsonValue, and java lacks any trait-like way to add this functionality to existing types, so you would have to change the signature to this:

    static JsonObject of(Map<String, ? extends Object> map);
Now you can pass any Object in, but the typechecker can't ensure that it is convertible to json anymore. I.e. it will have to check at runtime that it's either JsonValue or another type that is has a known conversion for (Integer, Double, String, List, Map, etc.). The jackson ObjectMapper e.g. has a lot of configuration available to tell it how to do these conversions on arbitrary types, and I think they want to eliminate that kind of ceremony.

It does seem like any serious application is going to use another library, and this will be useful for very simple json usage or single-file hello-world type programs (e.g. to go along with Implicitly Defined Classes and the Flexible Launch Protocol).

A Modest Proposal that will never be implemented: add an interface to String, Boolean, Integer, Long, Float and Double. Because all these types already implement "toString" (and I believe their toString representations are compatible with JSON), it can be a pure marker interface.

JSON String requires escaping of control characters. .toString() on a String is (hopefully) the identity.

For the "quick one-off script" case (where Implicitly Declared Classes shine), I think the most galling ceremony in this example is explicitly converting all N items in a list of literals into JsonValues for JsonArray.

This would help a lot:

    public interface JsonArray extends JsonValue {
        static JsonArray of(JsonValue... elements) { ... }
        static JsonArray of(String... elements) { ... }
        static JsonArray of(Double... elements) { ... }
        static JsonArray of(Integer... elements) { ... }
        static JsonArray of(Boolean... elements) { ... }
    }
Then, you could at least write:

    IO.println(JsonObject.of(Map.of("providers",
        JsonArray.of("SUN", "SunRsaSign", "SunEC"))));
And for JsonObject, a little fluent builder API would probably knock out a lot of ceremony, too.

    JsonObject json = JsonObject.builder()
        .put("name", "John")
        .put("age", 30)
        .put("active", true)
        .put("providers", JsonArray.of("SUN", "SunEC"))
        .build();
The alternative today looks quite ceremonious:

    JsonObject json= JsonObject.of(Map.of(
        "name", JsonString("John"),
        "age", JsonNumber(30),
        "active", JsonBoolean(true),
        "providers", JsonArray.of(List.of(
            JsonString("SUN"),
            JsonString("SunRsaSign"),
            JsonString("SunEC")
        ))
    ));