2

I am attempting to edit an OpenAPI specification by changing all parameters to be nullable. A parameter definition looks like this:

{
    "name": "foo",
    "required": true,
    "type": "string"
}

They are contained in a parameters array that can be anywhere in the document. What I need is to append "x-nullable": true to any parameter containing a type property.

Sample data:

{
    "parameters": [
        {"notype": "x"},
        {"type": "x"}
    ],
    "foo": {
        "parameters": [
            {"type": "y"}
        ]
    },
    "bar": {
        "baz": {
            "parameters": [
                {"type": "z"}
            ]
        }
    }
}

Desired output:

{
    "parameters": [
        {"notype": "x"},
        {
            "type": "x",
            "x-nullable": true
        }
    ],
    "foo": {
        "parameters": [
            {
                "type": "y",
                "x-nullable": true
            }
        ]
    },
    "bar": {
        "baz": {
            "parameters": [
                {
                    "type": "z",
                    "x-nullable": true
                }
            ]
        }
    }
}

The closest I could get was this:

.. | (.parameters[] | select(.type)) += {"x-nullable":true}

It successfully changes one of the items in my test document, but the results are inconsistent and seem to be based on the structure I choose for sample data.

1 Answer 1

4

The following jq expression applies an update to the value of all parameters keys found in the document. It is assumed that the parameters key always refers to an array. The update assigns true to the x-nullable key of all array elements with a type key.

The recursion is done with walk() (applies an expression to each value in the document, recursively) rather than with the recursive decent operator .. (extracts each value of the document, recursively).

walk(
    if type == "object" and has("parameters")
    then
        .parameters |= map(select(has("type"))."x-nullable" = true)
    else
        .
    end
)

It is safer to use select(has("type")) to select objects that have the type field, since using select(.type) would miss objects whose type value was false or null.

Testing on the sample document in the question:

$ jq 'walk(if type == "object" and has("parameters") then .parameters |= map(select(has("type"))."x-nullable" = true) else . end)' file
{
  "parameters": [
    {
      "notype": "x"
    },
    {
      "type": "x",
      "x-nullable": true
    }
  ],
  "foo": {
    "parameters": [
      {
        "type": "y",
        "x-nullable": true
      }
    ]
  },
  "bar": {
    "baz": {
      "parameters": [
        {
          "type": "z",
          "x-nullable": true
        }
      ]
    }
  }
}
1
  • 1
    Thank you; I have used jq many times to extract data from JSON but whenever I need to change data it becomes big trouble for me! Commented Feb 28 at 19:47

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.