style comments in JSON

I'm dealing with systems which manipulate "relaxed" JSON data which includes shell-style # line comments:

[
  {
    # Batman
    "first-name": "Bruce",
    "last-name": "Wayne"
  },
  {
    # Superman
    "first-name": "Clark",
    "last-name": "Kent"
  }
]

The part of the system I'm working on uses json-lib - which I'm surprised to discover is tolerant of the shell-style comments - to parse the JSON input.

I need to extract some additional annotation from those comments, but json-lib seems to just discard them without providing an API for reading them:

JSONObject map = (JSONObject)JSONSerializer.toJSON("{n"+
                                                   "    # Batmann" + // note the shell-style # comment
                                                   "    "first-name": "Bruce",n" +
                                                   "    "last-name": "Wayne"n" +
                                                   "}");
System.out.println(map.toString());
/* <<'OUTPUT'
 * {"first-name":"Bruce","last-name":"Wayne"}
 * OUTPUT
 * note the absence of the shell-style comment
 */

This makes sense since comments aren't part of the JSON spec and I'm lucky json-lib doesn't just choke when parsing them in the first place.

Of note:

  • other systems consume this same JSON and the annotations need to be transparent to them, so the JSON structure can't be modified by adding properties for the comments instead.
  • not all the components and objects in my system have access to the raw JSON source: one component reads the file and parses it using JSONlib and passes de-serialized maps etc around.
  • How can I read and parse these comments while processing the JSON input? Is there a library which will allow me to read them and relate them to their position in the JSON - can I easily connect the Batman comment to the "Bruce Wayne" entry?

    I'm currently using json-lib, but I'm open to investigating other JSON libraries and equally open to using other languages which extend JSON, such as YAML - but I'm not sure those tools will allow me to read and process the comments in my input.


    What I chose to do is modify the public domain JSON.org library to support shell comments and adding comments to the JSON object, as I've done in this GitHub gist:

    https://gist.github.com/peteroupc/5529464

    Example of use:

    JSONObject obj=new JSONObject("{ # Commentn"+
            ""first-key":"first-value",n"+
            ""second-key":"second-value" }",
            JSONObject.OPTION_SHELL_COMMENTS | // Support SHELL-style comments
            JSONObject.OPTION_ADD_COMMENTS // Incorporate comments in the JSON object
    );
    System.out.println(obj); // Output the JSON object
    

    Example output. Note that the comment occurs in a key called "@comment".

    {"second-key":"second-value","@comment":"Comment","first-key":"first-value"}
    

    But one of your requirements is that "the JSON structure can't be modified by adding properties for the comments instead." That means the comments must be associated to the JSON objects in some other way. Fortunately, a specification called JSON Pointer was recently published as RFC 6901. JSON Pointer is a string that refers to a JSON object within another JSON object. Accordingly, additional steps are required: find the child objects with "@comment" keys, remove the keys, and create a mapping of JSON pointers to comments.

    This is illustrated by the code below.

    // Objects with comments associated with them will
    // now contain an "@comment" key; get the JSON Pointers
    // (RFC6901) to these objects and remove the "@comment" keys.
    Map<String,Object> pointers=JSONPointer.getPointersWithKeyAndRemove(obj,"@comment");
    // For each JSON Pointer, get its corresponding object.
    // They will always be JSONObjects.
    for(String pointer : pointers.keySet()){
        JSONObject subobj=(JSONObject)JSONPointer.getObject(obj,pointer);
        System.out.println(subobj); // Output the object
        System.out.println(pointers.get(pointer)); // Output the key's value
    }
    

    Example output:

    {"second-key":"second-value","first-key":"first-value"}
    Comment
    

    Since JSON Pointer is new, I wrote my own implementation of it and included it in the GitHub gist.


    Here are further examples to clarify.

    Given this JSON array (use JSONArray instead of JSONObject in this example):

    [{ # foo
    "foo-key":"foo-value"},
    { # This is a
     # quite long comment.
    "bar-key":"bar-value"}]
    

    The result would be:

    {"foo-key":"foo-value"}
    foo
    {"bar-key":"bar-value"}
    This is a quite long comment.
    

    As a result, multiple comments are coalesced into a single comment. But given this JSON Array:

    [{ # foo
    "foo-key":"foo-value"},
    { # This is a
     # quite long comment.
    "bar-key":"bar-value"
     # This is another comment.
      }]
    

    The result would be:

    {"foo-key":"foo-value"}
    foo
    {"bar-key":"bar-value"}
    This is another comment.
    

    As a result, multiple comments that occurred in multiple places on the "bar" object are not coalesced.


    other systems consume this same JSON and the annotations need to be transparent to them, so the JSON structure can't be modified by adding properties for the comments instead

    Using comments in messages to pass data between systems doesn't seem a good practice. . Eg XML wouldn't support that.

    Why not simply incorporate the important "comments" as data? That's what it is if the other system is using it. :^)

    链接地址: http://www.djcxy.com/p/20126.html

    上一篇: 如何在Flask中获得发布的json?

    下一篇: JSON风格的评论