4

I have a JSON file like this

{
    "hierarchy": {
        "structure": {
            "card_11001": [
                "addCard_4111"
            ],
            "container_11006": [
                "mainContainer_11007",
                "subContainer_10016"
            ],
            "mainContainer_11007": [
                "paymentMethodList_10001"
            ],
            "orderWrap_10012": [
                "orderSummary_10005"
            ],
            "paymentMethodList_10001": [
                "card_11001",
                "placeOrder_10013"
            ],
            "root_10000": [
                "payNotice_11011",
                "payNotice_10020",
                "container_11006",
                "placeOrderResultAction_10004"
            ],
            "subContainer_10016": [
                "orderWrap_10012",
                "footer_10014"
            ]
        }
    }
}

And I want to insert

"offline_11018": [
    "instruction_908",
    "checkboxList_11019"
]

Between "mainContainer_11007" and "orderWrap_10012" so the result I want should look like this:

{
    "hierarchy": {
        "structure": {
            "card_11001": [
                "addCard_4111"
            ],
            "container_11006": [
                "mainContainer_11007",
                "subContainer_10016"
            ],
            "mainContainer_11007": [
                "paymentMethodList_10001"
            ],
            "offline_11018": [
                "instruction_908",
                "checkboxList_11019"
            ],
            "orderWrap_10012": [
                "orderSummary_10005"
            ],
            "paymentMethodList_10001": [
                "card_11001",
                "placeOrder_10013"
            ],
            "root_10000": [
                "payNotice_11011",
                "payNotice_10020",
                "container_11006",
                "placeOrderResultAction_10004"
            ],
            "subContainer_10016": [
                "orderWrap_10012",
                "footer_10014"
            ]
        }
    }
}

All I know is that I can only append it to the end of file with

jq --raw-output '.hierarchy.structure + {"offline_11018": ["instruction_908","checkboxList_11019"]}'

But that's not what I want, I want to insert it between two other keys. How can I do it with the jq command?

peak
  • 105,803
  • 17
  • 152
  • 177
Joe
  • 791
  • 1
  • 9
  • 24
  • 1
    The keys in an objects are unordered. As long as the new key is added to the correct object, it doesn't matter where the key exists. – chepner Apr 02 '18 at 16:50

1 Answers1

2

The simplest approach would be to use to_entries to convert .hierarchy.structure into an array, perform the insertion, and then use from_entries to reconstitute the object, along the lines of:

.hierarchy.structure |= (to_entries
  | ... as $ix
  | .[:$ix] + ($x | to_entries) + .[$ix:]
  | from_entries)

The above sketch of course would need to be modified if it is possible that the item defining the insertion point cannot be found.

indexof/1

Here's a useful "def" for finding the least index for which some condition holds:

# If the input is an array, emit the least index, $i, 
# for which `.[$i]|f` is truthy, otherwise emit null.
# Works similarly if the input is a JSON object.
def indexof(f):
  label $out
  | foreach .[] as $x (null; .+1;
      if ($x|f) then (.-1, break $out) else empty end) // null;

Solution using indexof

Putting the above pieces together:

{"offline_11018": [ "instruction_908", "checkboxList_11019" ]} as $x
| .hierarchy.structure |= (to_entries
    | (1 + indexof( .value | index("mainContainer_11007") )) as $ix
    | .[:$ix] + ($x | to_entries) + .[$ix:]
    | from_entries)
peak
  • 105,803
  • 17
  • 152
  • 177