jsonjq

How to transform JSON array elements recursively into objects using JQ filter


I want to transform this JSON

{
    "property": "value",
    "array1": [
        {
            "name": "A",
            "propertyA1": "1",
            "propertyA2": "2"
        },
        {
            "name": "B",
            "propertyB1": "1",
            "array2": [
                {
                    "name": "C",
                    "propertyC1": "1",
                    "propertyC2": "2"
                }
            ]
        }
    ]
}

into that using a JQ filter.

{
    "property": "value",
    "array1": {
        "A": {
            "propertyA1": "1",
            "propertyA2": "2"
        },
        "B" : {
            "propertyB1": "1",
            "array2": {
                "C" : {
                    "propertyC1": "1",
                    "propertyC2": "2"
                }
            }
        }
    }
}

The difficulty is to make this work recursively. Moreover, only arrays who possess an object with a property name should be considered. I had a few attempts but it already fails if I want to add a new property do the arrays (I know it's not possible, since it is an array).


Solution

  • You basically want to turn each array into an object with each item's .name field turned into a key. You could use from_entries which requires each key and value as .name (or .key) and .value fields, so all you have to do is to set up a .value without the .name field. walk the document tree to apply this to each array.

    walk(arrays |= (map(.value = del(.name)) | from_entries))
    
    {
      "property": "value",
      "array1": {
        "A": {
          "propertyA1": "1",
          "propertyA2": "2"
        },
        "B": {
          "propertyB1": "1",
          "array2": {
            "C": {
              "propertyC1": "1",
              "propertyC2": "2"
            }
          }
        }
      }
    }
    

    Demo