Search code examples
jsonyamljson.netjson5

Is there a JSON with comments to YAML converter?


There are a number of JSON variants that accept comments (JSON with comments, JSON 5, etc.). There are plenty of tools available that convert JSON to YAML and vice versa. Does there exist such a converter from JSON to YAML that (1) accepts JSON comments and (2) converts these comments to YAML comments?


Solution

  • As of YAML 1.2.0 (Jul 21, 2009), YAML is a superset of JSON. Thus, technically, as long as the commenting style is YAML-compliant (using # not // etc.), all "JSON variants that accept comments" by themselves are already valid YAML documents.

    To alter the styling of some YAML (including JSON) content, you only need to find an appropriate (general) YAML(-only) processor that preserves (all) comments.

    Here's one example using mikefarah/yq v4.35.1 (not to be confused with kislyuk/yq of the same name which does not preserve comments). With a sample input.json containing

                  # before the document
    {             # inside an object, before first key
      "a":        # inside an object, between key+colon and value
        null      # inside an object, between value and comma
      ,           # inside an object, between comma and key
      "b": [      # inside an array, before first item
        1         # inside an array, between item and comma
        ,         # inside an array, between comma and item
        true      # inside an array, after last item
      ]           # inside an object, after last item
    }             # outside the document, inline with it
                  # after the document
    

    you can remove the JSON-styling on all levels using the filter ... style = "":

    yq '... style = ""' < input.json
    
    # before the document
    a: null # inside an object, between key+colon and value
    
    # inside an object, between value and comma
    # inside an object, between comma and key
    b:
      - 1 # inside an array, between item and comma
      # inside an array, between comma and item
      - true # inside an array, after last item
    
    # after the document
    

    As you can see, four comments get lost: the ones before a first key or item, the one after the last object item, and the one inline with the last closing brace. Examine your use-case, and/or consider extending the filter with some comment operators offered by yq. For example, you could add the last one missing by combining the line_comment with the foot_comment for the document-level only:

    yq '... style = "" | . foot_comment = line_comment + "\n" + foot_comment' < input.json
    
    # before the document
    a: null # inside an object, between colon and value
    
    # inside an object, between value and comma
    # inside an object, between comma and key
    b:
      - 1 # inside an array, between item and comma
      # inside an array, between comma and item
      - true # inside an array, after last item
    
    # outside the document, inline with it
    # after the document
    

    Regarding mikefarah/yq specifically, note that the current version (v4.35.1) cannot read a JSON input where an object field's key and the subsequent colon are on separate lines (so you'd also expect comments to live in between):

    {
      "a"       # inside an object, between key and colon
      :         # inside an object, between colon and value
      null      # inside an object, between value and comma
    }
    
    Error: bad file '-': yaml: line 1: did not find expected ',' or '}'
    

    Also see https://yaml.org/ which has a long list of YAML processors and language frameworks. Some of them also handle comments, so try them out as one of them may just exactly fit your commenting scenario.