Search code examples
jsonnestedkeyjq

How to access key at any level?


I have this input file

{
    "description": "this is a fake description",
    "owner": "john",
    "region": "us-east-1",
    "topics": {
        "For collecting responses for prod1": {
            "suffix_name": "response-to-hogwarts.fifo",
            "tags": {}
        }
    },
    "queues": {
        "For collecting responses and requests from test1": {
            "suffix_name": "rr_sf_name.fifo",
            "tags": {}
        },
        "For collecting responses for test2": {
            "suffix_name": "response-to-hogwarts.fifo",
            "tags": {}
        }
    },
    "subscriptions": {
        "For receiving harry_potter requests": {
            "topic": {
                "suffix_name": "harry_potter.fifo",
                "tag": "staging"
            },
            "queue": {
                "suffix_name": "rr_sf_name.fifo"
            }
        },
        "For receiving harry_potter requests from test3": {
            "topic": {
                "suffix_name": "harry_potter.fifo",
                "tag": "harry_potter_hogwarts"
            },
            "queue": {
                "suffix_name": "rr_sf_name.fifo"
            }
        },
        "For receiving demo requests": {
            "topic": {
                "suffix_name": "demo.fifo",
                "tag": "staging"
            },
            "queue": {
                "suffix_name": "rr_sf_name.fifo"
            }
        },
        "For receiving demo requests from test4 through connector": {
            "topic": {
                "suffix_name": "demo.fifo",
                "tag": "harry_potter_hogwarts"
            },
            "queue": {
                "suffix_name": "rr_sf_name.fifo"
            }
        },
        "For receiving testing responses for hogwarts": {
            "topic": {
                "suffix_name": "response-to-hogwarts.fifo"
            },
            "queue": {
                "suffix_name": "response-to-hogwarts.fifo"
            }
        }
    }
}

Now I want to remove the ".fifo" suffix from the value of ALL the suffix_name fields, at any level

Example output (truncated for brevity)

    "topics": {
        "For collecting responses for prod1": {
            "suffix_name": "response-to-hogwarts",
            "tags": {}
        }
    },

Now I came up with this, which is working for me.

.queues |= with_entries(.value.suffix_name |= sub(".fifo";""))
| .topics |= with_entries(.value.suffix_name |= sub(".fifo";""))
| .subscriptions |= with_entries(.value |= with_entries(.value |= with_entries(.value |= rtrimstr(".fifo"))))

I want to know, if there is a better way, using recurse or something, to parse through all keys and if the key is suffix_name, trim the ".fifo" from the value.


Solution

  • You could use walk:

    walk(if type=="object" and .suffix_name 
         then .suffix_name |= sub("[.]fifo$";"") else . end)
    

    Alternatively, just use |=:

     (.. | select(type == "object" and .suffix_name) | .suffix_name) 
      |=  sub("[.]fifo$";"")