<div dir="ltr">I would like to add JSON comments from my perspective.<br><br>I had a requirement of working with JSON in java multiple times during working on the university assignments recently. Since those are small, often one-time-open projects, I did not want (or, often, it was forbidden by assignment) to pull in whole jackson with modules and staff, along with gradle and rocket launchers, so i had to work out my own small parser for the JSON, since this is a pretty trivial task in its core. I want to note that none of the times I had the necessity to write comments in the JSON or parse input with them.That is why I think that for the cases when you would use raw jdk JSON API, comments in the JSON are extremely exotic.<br><br>On the other hand, If you are working on the full-blown enterprise-grade project, and want the JSON to facilitate your configs, then <strike>use yaml</strike> you will most likely already have your JSON parser with comments support included by your framework, whether it is jackson, gson or something else.<br><br>I think the key point here is that jdk JSON API, as it seems to me, does not aim to obsolete any of the existing (de)serialization libraries, and is rather intended to be the core, backbone of those, along with the direct JSON support for the simplest cases, much like virtually no one uses security mechanisms of the JDK directly instead of relying on libraries/frameworks aka spring security. I think voice on whether to add some non-standard syntax support for JSON here belongs to maintainers of such libraries. To me, at least, it seems like this libs will be able to use this API with some required preprocessing done on the raw strings before, via regex or any other more performant/comfortable method<br><br>Best regards </div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Fri, May 16, 2025 at 4:17 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>

  
  <div>
    At first, we were hopeful that we could jump right to JSON5, which
    appears at first glance to be a strictly lexical, more permissive
    grammar for JSON (supporting comments, trailing commas, more
    flexible quoting, white space, etc.)  If that were actually true,
    this would have been a slam dunk, since all these lexical niceties
    don't have an impact on the parsed results.  And JSON5 has been
    gaining some traction, so it probably could have been a justifiable
    move to jump right to that.  <br>
    <br>
    But then we discovered that JSON5 also sneaks in some semantics, by
    also supporting the exotic numeric values (NaN, infinities, signed
    zero), which now has consequences for "what is a number", the
    numeric representation, the API for unpacking numeric values, etc. 
    (Having multiple parsers is one thing; having multiple parsers that
    produce different semantics is entirely another.)  And inventing a
    new "JSON5 but not quite" subset would be doing no one any favors. 
    <br>
    <br>
    Jsonc seems to be entirely a MS-ecosystem thing; it does not have
    broad enough traction to be the "one grammar" we accept.  So pure
    JSON, as specification-challenged as it is, is the logical, though
    sad, conclusion (for now.)<br>
    <br>
    <br>
    <br>
    <div>On 5/16/2025 9:02 AM, Lars Bruun-Hansen
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <p><br>
        Great work.</p>
      <p><br>
      </p>
      <p>I feel the elephant in the room needs to addressed: JSON
        comments. I haven't tested the proposed lib but I cannot see it
        mentioned so I'm assuming that comments are not supported.<br>
      </p>
      <p>For better or worse, the use of jsonc (JSON with comments) is
        everywhere in some ecosystems. Unsurprisingly this happens often
        when JSON is used as a config file format. Looking at you,
        Microsoft.</p>
      <p>It would be nice if the JDK's build-in JSON parser at least
        recognized this.</p>
      <p>I'm well aware that comments are frowned upon in JSON and not
        part of neither the spec at <a href="http://www.json.org" target="_blank">www.json.org</a>
        nor the RFC-8259.</p>
      <p>Yet, I advocate the JDK JSON library should optionally allow
        comments to be ignored when PARSING. This should be an opt-in
        feature that would technically treat comments as whitespace
        during the parsing process.<br>
      </p>
      <p>This would also be in line with what many other parsers do. For
        example, Jackson has "ALLOW_COMMENTS" feature [1]. Also, by
        comparison, the build-in parser in the .NET world, known as
        System.Text.Json, also supports this [2]. <br>
      </p>
      <p><br>
      </p>
      <p><br>
      </p>
      <p>The "discoverer" of JSON, Douglas Crowford, had this to say [3]
        on the topic:</p>
      <p><br>
      </p>
      <p>[QUOTE]<br>
      </p>
      <p>I removed comments from <abbr title="JavaScript Object Notation">JSON</abbr> because I saw
        people were using them to hold parsing directives, a practice
        which would have destroyed interoperability. I know that the
        lack of comments makes some people sad, but it shouldn't. </p>
      <p>Suppose you are using <abbr title="JavaScript Object Notation">JSON</abbr>
        to keep configuration files, which you would like to annotate.
        Go ahead and insert all the comments you like. Then pipe it
        through JSMin before handing it to your <abbr title="JavaScript Object Notation">JSON</abbr> parser.</p>
      <p> [/QUOTE]</p>
      <p><br>
      </p>
      <p>By not having the ability to ignore comments when parsing we
        would effectively force users to use another parser first or a
        minifier. I doubt beginners would appreciate that. <br>
      </p>
      <p><br>
      </p>
      <p>BTW: The test suite already has tests for comments.</p>
      <p><br>
      </p>
      <p>/Lars<br>
      </p>
      <p><br>
      </p>
      <p>[1]:
        <a href="https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-core/2.19.0/com/fasterxml/jackson/core/JsonParser.Feature.html#ALLOW_COMMENTS" target="_blank">https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-core/2.19.0/com/fasterxml/jackson/core/JsonParser.Feature.html#ALLOW_COMMENTS</a></p>
      <p>[2]:
        <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonreaderoptions?view=net-9.0#properties" target="_blank">https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonreaderoptions?view=net-9.0#properties</a></p>
      <p>[3]: <a href="https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr" target="_blank">https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr</a></p>
      <p><br>
      </p>
      <p><br>
      </p>
      <p><br>
      </p>
      <div>On 16/05/2025 01.44, Ethan McCue
        wrote:<br>
      </div>
      <blockquote type="cite">
        <div dir="ltr">I present for your consideration the library I
          made when spiraling about this problem space a few years ago<br>
          <br>
          <a href="https://github.com/bowbahdoe/json" target="_blank">https://github.com/bowbahdoe/json</a><br>
          <br>
          <a href="https://javadoc.io/doc/dev.mccue/json/latest/dev.mccue.json/dev/mccue/json/package-summary.html" target="_blank">https://javadoc.io/doc/dev.mccue/json/latest/dev.mccue.json/dev/mccue/json/package-summary.html</a><br>
          <br>
          Notably missing during the design process here were patterns,
          hence the JsonDecoder design. I haven't been able to evaluate
          how patterns affect that on account of them not being out.<br>
          <br>
          I will more thoroughly peruse the draft of java.util.json at a
          later date, but my initial observations/comments:<br>
          <br>
          * I am not sure having JsonValue be distinct from Json has
          value.<br>
          * toUntyped feels a little strange to me - the only type
          information presumably lost is the sealed-ness of the
          hierarchy. The interplay between that and toNumber is also a
          little unnerving.<br>
          * One notion that I found helpful was that a class could be
          "json encodable," meaning there is a method to call to obtain
          a canonical json representation.<br>
          <br>
          <font face="monospace">record Person(String name) implements
            JsonEncodable {</font><br>
          <font face="monospace">    </font><a class="gmail_plusreply" id="m_-3855213741326352630m_-2004856809941181964plusReplyChip-0" style="font-family:monospace">@Override<br>
          </a><font face="monospace">    public Json toJson() {</font><br>
          <font face="monospace">        return Json.objectBuilder()</font><br>
          <font face="monospace">            .put("namen", name)</font><br>
          <font face="monospace">            .build();</font><br>
          <font face="monospace">    }</font><br>
          <font face="monospace">}</font><br>
          <br>
          <font face="arial, sans-serif">Which helper methods like </font><font face="monospace">Json#of(List<? extends
            JsonEncodable>)</font><font face="arial, sans-serif"> could
            make use of. </font><font face="monospace">Json</font><font face="arial, sans-serif"> itself (</font><font face="monospace">JsonValue</font><font face="arial, sans-serif"> in your prototype) could then have
            a vacuous implementation.<br>
            <br>
            * Terminology wise - I went with reading/writing for the
            actual parsing/generation of json and encoding/decoding for
            the mapping of those representations to/from specific
            classes. The merits are not top of mind, just noting the
            difference. read/write vs parse/toString+toDisplayString<br>
            * One thing I did was make the helper methods in </font><font face="monospace">Json</font><font face="arial, sans-serif"> null
            tolerant and the ones in the specific subtypes like </font><font face="monospace">JsonString</font><font face="arial, sans-serif"> not. This was because from what I
            saw of usages of javax.json/jakarta.json that nullability
            was a footgun and correcting for it required changes to code
            structure (breaking up builder chains with </font><font face="monospace">if (x != null)</font><font face="arial, sans-serif"> checks)<br>
          </font>* The functionality you want from <font face="monospace">JsonNumber </font><font face="arial, sans-serif">could be achieved by making it just
            extend </font><font face="monospace">Number (</font><a href="https://github.com/bowbahdoe/json/blob/main/src/main/java/dev/mccue/json/JsonNumber.java" target="_blank">https://github.com/bowbahdoe/json/blob/main/src/main/java/dev/mccue/json/JsonNumber.java</a>)
          instead of a bespoke <font face="monospace">toNumber</font><font face="arial, sans-serif">. You need the extra methods to go
            to big decimal and co, but it's just an extension to the
            behavior of Number at that point.<br>
          </font>* JsonObject and JsonArray could implement
          Map<String, Json> and List<Json> respectively.
          This lowers the need for toUntyped() - since presumably one of
          the use cases for that is turning the json tree into something
          that more generic map/list traversal code can handle. It also
          complicates any lazy loading somewhat.<br>
          * Assuming patterns can be placed on interfaces, you might
          want to consider something similar to <font face="monospace">JsonDecoder</font><font face="arial, sans-serif">, but with a pattern instead of a
            method that throws an exception.<br>
          </font><br>
          <span style="font-family:monospace">// Where here fromJson
            would box up the logic for testing and extracting from each
            element in the array.</span><br>
          <font face="monospace">List<Person> people = array(json,
            Person::fromJson);<br>
          </font><br>
          * I don't think there is sufficient cause for anything to be
          non-sealed at this point.<br>
          * JsonBoolean and JsonNull do not have reasonable alternative
          implementations - as far as I can imagine, maybe i'm wrong -
          so maybe those can just be final classes?<br>
          * If you seal up the whole hierarchy then its pretty trivial
          to make it serializable (<a href="https://github.com/bowbahdoe/json/blob/main/src/main/java/dev/mccue/json/serialization/JsonSerializationProxy.java" target="_blank">https://github.com/bowbahdoe/json/blob/main/src/main/java/dev/mccue/json/serialization/JsonSerializationProxy.java</a>)<br>
          <br>
          <br>
          <br>
        </div>
        <br>
        <div class="gmail_quote">
          <div dir="ltr" class="gmail_attr">On Thu, May 15, 2025 at
            11:29 PM Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi
            Paul,<br>
            yes, not having a simple JSON API in Java is an issue for
            beginners.<br>
            <br>
            It's not clear to me why JsonArray (for example) has to be
            an interface instead of a record ?<br>
            <br>
            I understand why Json.parse() only works on String and
            char[] but the API make it too easy to have many performance
            issues.<br>
            I think you need versions using a Reader and a Path.<br>
            Bonus point, if there is a method walk() that also returns a
            JsonValue but the List/Map inside JsonArray/JsonObject are
            populated lazily.<br>
            <br>
            Minor point: Json.toDisplayString() should takes a second
            parameters indicating the number of spaces used for the
            indentation (like JSON.stringify in JS).<br>
            <br>
            regards,<br>
            Rémi<br>
            <br>
            ----- Original Message -----<br>
            > From: "Paul Sandoz" <<a href="mailto:paul.sandoz@oracle.com" target="_blank">paul.sandoz@oracle.com</a>><br>
            > To: "core-libs-dev" <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
            > Sent: Thursday, May 15, 2025 10:30:42 PM<br>
            > Subject: Towards a JSON API for the JDK<br>
            <br>
            > Hi,<br>
            > <br>
            > We would like to share with you our thoughts and plans
            towards a JSON API for<br>
            > the JDK.<br>
            > Please see the document below.<br>
            > <br>
            > -<br>
            > <br>
            > We have had the pleasure of using a clone of this API
            in some experiments we are<br>
            > conducting with<br>
            > ONNX and code reflection [1]. Using the API we were
            able to quickly write code<br>
            > to ingest and convert<br>
            > a JSON document representing ONNX operation schema into
            instances of records<br>
            > modeling the schema<br>
            > (see here [2]).<br>
            > <br>
            > The overall out-of-box experience with such a minimal
            "batteries included” API<br>
            > has so far been positive.<br>
            > <br>
            > Thanks,<br>
            > Paul.<br>
            > <br>
            > [1] <a href="https://openjdk.org/projects/babylon/" rel="noreferrer" target="_blank">https://openjdk.org/projects/babylon/</a><br>
            > [2]<br>
            > <a href="https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/opgen/src/main/java/oracle/code/onnx/opgen/OpSchemaParser.java#L87" rel="noreferrer" target="_blank">https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/opgen/src/main/java/oracle/code/onnx/opgen/OpSchemaParser.java#L87</a><br>
            > <br>
            > # Towards a JSON API for the JDK<br>
            > <br>
            > One of the most common requests for the JDK is an API
            for parsing and generating<br>
            > JSON. While JSON originated as a text-based
            serialization format for JSON<br>
            > objects ("JSON" stands for "JavaScript Object
            Notation"), because of its simple<br>
            > and flexible syntax, it eventually found use outside
            the JavaScript ecosystem as<br>
            > a general data interchange format, such as framework
            configuration files and web<br>
            > service requests/response formats.<br>
            > <br>
            > While the JDK cannot, and should not, provide libraries
            for every conceivable<br>
            > file format or protocol, the JDK philosophy is one of
            "batteries included",<br>
            > which is to say we should be able to write basic
            programs that use common<br>
            > protocols such as HTTP, without having to appeal to
            third party libraries.<br>
            > The Java ecosystem already has plenty of JSON
            libraries, so inclusion in<br>
            > the JDK is largely meant to be a convenience, rather
            than needing to be the "one<br>
            > true" JSON library to meet the needs of all users.
            Users with specific needs<br>
            > are always free to select one of the existing
            third-party libraries.<br>
            > <br>
            > ## Goals and requirements<br>
            > <br>
            > Our primary goal is that the library be simple to use
            for parsing, traversing,<br>
            > and generating conformant JSON documents. Advanced
            features, such as data<br>
            > binding or path-based traversal should be possible to
            implement as layered<br>
            > features, but for simplicity are not included in the
            core API. We adopt a goal<br>
            > that the performance should be "good enough", but where
            performance<br>
            > considerations conflict with simplicity and usability,
            we will choose in favor<br>
            > of the latter.<br>
            > <br>
            > ## API design approach<br>
            > <br>
            > The description of JSON at `https:://<a href="http://json.org" rel="noreferrer" target="_blank">json.org</a>` describes a JSON
            document using<br>
            > the familiar "railroad diagram":<br>
            > ![image](<a href="https://www.json.org/img/value.png" rel="noreferrer" target="_blank">https://www.json.org/img/value.png</a>)<br>
            > <br>
            > This diagram describes an algebraic data type (a sum of
            products), which we<br>
            > model directly with a set of Java interfaces:<br>
            > <br>
            > ```<br>
            > interface JsonValue { }<br>
            > interface JsonArray extends JsonValue {
            List<JsonValue> values(); }<br>
            > interface JsonObject extends JsonValue { Map<String,
            JsonValue> members(); }<br>
            > interface JsonNumber extends JsonValue { Number
            toNumber(); }<br>
            > interface JsonString extends JsonValue { String
            value(); }<br>
            > interface JsonBoolean extends JsonValue  { boolean
            value(); }<br>
            > interface JsonNull extends JsonValue { }<br>
            > ```<br>
            > <br>
            > These interfaces have (hidden) companion implementation
            classes that admit<br>
            > greater flexibility of implementation than modeling
            them directly with records<br>
            > would permit.<br>
            > Further, these interfaces are unsealed. We compromise
            on the sealed sum of<br>
            > products to enable<br>
            > alternative implementations, for example to support
            alternative formats that<br>
            > encode the same information in a JSON document but in a
            more efficient form than<br>
            > text.<br>
            > <br>
            > The API has static methods for parsing strings into a
            `JsonValue`, conversion to<br>
            > and from purely untyped representations (lists and
            maps), and factory methods<br>
            > for building JSON documents. We apply composition
            consistently, e.g, a<br>
            > JsonString has a string, a JsonObject has a map of
            string to JsonValue, as<br>
            > opposed to extension for structural JSON values.<br>
            > <br>
            > It turns out that this simple API is almost all we need
            for traversal. It gives<br>
            > us an immutable representation of a document, and we
            can use pattern matching to<br>
            > answer the myriad questions that will come up (Does
            this object have key X? Does<br>
            > it map to a number? Is that number representable as an
            integer?) when going<br>
            > from an untyped format like JSON to a more strongly
            typed domain model.<br>
            > Given a simple document like:<br>
            > <br>
            > ```<br>
            >    {<br>
            >        "name": "John”,<br>
            >        "age": 30<br>
            >    }<br>
            > ```<br>
            > <br>
            > we can parse and traverse the document as follows:<br>
            > <br>
            > ```<br>
            > JsonValue doc = Json.parse(inputString);<br>
            > if (doc instanceof JsonObject o<br>
            >    && o.members().get("name") instanceof
            JsonString s<br>
            >    && s.value() instanceof String name<br>
            >    && o.members().get("age") instanceof
            JsonNumber n<br>
            >    && n.toNumber() instanceof Long l &&
            l instanceof int age) {<br>
            >            // use "name" and "age"<br>
            >        }<br>
            > ```<br>
            > <br>
            > Later, when the language acquires the ability to expose
            deconstruction patterns<br>
            > for arbitrary interfaces (similar to today's record
            patterns, see<br>
            > <a href="https://openjdk.org/projects/amber/design-notes/patterns/towards-member-patterns" rel="noreferrer" target="_blank">https://openjdk.org/projects/amber/design-notes/patterns/towards-member-patterns</a>),<br>
            > this will be simplifiable to:<br>
            > <br>
            > ```<br>
            > JsonValue doc = Json.parse(inputString);<br>
            > if (doc instanceof JsonObject(var members)<br>
            >    && members.get("name") instanceof
            JsonString(String name)<br>
            >    && members.get("age") instanceof
            JsonNumber(int age)) {<br>
            >            // use "name" and "age"<br>
            >        }<br>
            > ```<br>
            > <br>
            > So, overtime, as more pattern matching features are
            introduced we anticipate<br>
            > improved use of the API. This is a primary reason why
            the API is so minimal.<br>
            > Convenience methods we add today, such as a method that
            accesses a JSON<br>
            > object component as say a JSON string or throws an
            exception, will become<br>
            > redundant in the future.<br>
            > <br>
            > ## JSON numbers<br>
            > <br>
            > The specification of JSON number makes no explicit
            distinction between integral<br>
            > and decimal numbers, nor specifies limits on the size
            of those numbers.<br>
            > This is a common source of interoperability issues when
            consuming JSON<br>
            > documents. Generally users cannot always but often do
            assume JSON numbers are<br>
            > parsable, without loss of precision, to IEEE
            double-precision floating point<br>
            > numbers or 32-bit signed integers.<br>
            > <br>
            > In this respect the API provides three means to operate
            on the JSON number,<br>
            > giving the user full control:<br>
            > <br>
            > 1. Underlying string representation can be obtained, if
            preserving syntactic<br>
            >   details such as leading or trailing zeros is
            important.<br>
            > 2. The string representation can be parsed to an
            instance of `BigDecimal`, using<br>
            >   `toBigDecimal` if preserving decimal numbers is
            important.<br>
            > 3. The string representation can be parsed into an
            instance of `Long`, `Double`,<br>
            >   `BigInteger`, or `BigDecimal`, using `toNumber`. The
            result of this method<br>
            >   depends on how the representation can be parsed,
            possibly losing precision,<br>
            >   choosing a suitably convenient numeric type that can
            then be pattern<br>
            >   matched on.<br>
            > <br>
            > Primitive pattern matching will help as will further
            pattern matching features<br>
            > enabling the user to partially match.<br>
            > <br>
            > ## Prototype implementation<br>
            > <br>
            > The prototype implementation is currently located into
            the JDK sandbox<br>
            > repository<br>
            > under the `json` branch, see<br>
            > here<br>
            > <a href="https://github.com/openjdk/jdk-sandbox/tree/json/src/java.base/share/classes/java/util/json" rel="noreferrer" target="_blank">https://github.com/openjdk/jdk-sandbox/tree/json/src/java.base/share/classes/java/util/json</a><br>
            > The prototype API javadoc generated from the repository
            is also available at<br>
            > <a href="https://cr.openjdk.org/~naoto/json/javadoc/api/java.base/java/util/json/package-summary.html" rel="noreferrer" target="_blank">https://cr.openjdk.org/~naoto/json/javadoc/api/java.base/java/util/json/package-summary.html</a><br>
            > <br>
            > ### Testing and conformance<br>
            > <br>
            > The prototype implementation passes all conformance
            test cases but two,<br>
            > available<br>
            > on <a href="https://github.com/nst/JSONTestSuite" rel="noreferrer" target="_blank">https://github.com/nst/JSONTestSuite</a>.
            The two exceptions are the ones which<br>
            > the<br>
            > prototype specifically prohibits, i.e, duplicated names
            in JSON objects<br>
            > (<a href="https://cr.openjdk.org/~naoto/json/conformance/results/parsing.html#35" rel="noreferrer" target="_blank">https://cr.openjdk.org/~naoto/json/conformance/results/parsing.html#35</a>).<br>
            > <br>
            > ### Performance<br>
            > <br>
            > Our main focus so far has been on the API design and a
            functional<br>
            > implementation.<br>
            > Hence, there has been less focus on performance even
            though we know there are a<br>
            > number of performance enhancements we can make
            eventually.<br>
            > We are reasonably happy with the current performance.
            The<br>
            > implementation performs well when compared to other
            JSON implementations<br>
            > parsing from string instances and traversing documents.<br>
            > <br>
            > An example of where we may choose simplicity and
            usability over performance<br>
            > is the rejection of JSON documents containing objects
            that in turn contain<br>
            > members<br>
            > with duplicate names. That may increase the cost of
            parsing, but simplifies the<br>
            > user<br>
            > experience for the majority of cases since if we
            reasonably assume JsonObjects<br>
            > are<br>
            > map-like, what should the user do with such members,
            pick one the last one?<br>
            > merge<br>
            > the values? or reject?<br>
            > <br>
            > ## A JSON JEP?<br>
            > <br>
            > We plan to draft JEP when we are ready. Attentive
            readers will observe that<br>
            > a JEP already exists, JEP 198: Light-Weight JSON API<br>
            > (<a href="https://openjdk.org/jeps/198" rel="noreferrer" target="_blank">https://openjdk.org/jeps/198</a>).
            We will<br>
            > either update this JEP, or withdraw it and draft a new
            one.<br>
          </blockquote>
        </div>
      </blockquote>
    </blockquote>
    <br>
  </div>

</blockquote></div>