Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find JSON key in all files and remove the corresponding key-value pair

I have a lot of files in which I need to find a string and if that string is there then I need to remove json block around that string from all those files.

For example:

I am looking for this string - "1234" in all my files. Each file has a huge json block which has string that I want to remove. So in all those files, string is like this in below two format:

First format is:

...
"data": {
    "1234": {
        "tt": true
    }
}
...

Second format with multiple json objects inside data:

...
"data": {
    "1234": {
        "tt": true
    },
    "7890": {
        "tt": true
    }
}
...

Now I need to come up with some script from where I can remove json object "1234" completely. So output should be:

For first format:

...
"data": {}
...

For second format:

...
"data": {
    "7890": {
        "tt": true
    }
}
...

Is this possible to do? I am in mac linux terminal. I can do a grep search and find the files but not sure how to remove the json object around that string from all the files.

Note: Each json file is in pretty format.

Update:

{
    "props": [
        {
            "property": "Hat",
            "data": {
                "1234": {
                    "tt": true
                },
                "7890": {
                    "tt": true
                }
            }
        }
    ]
}

Here is the snippet - https://jqplay.org/s/qXW_QUYFv0. If the property value is Hat then only I want to remove the key present but if property value is something else then I don't want to remove that key. Is there any way we can add this change as well?

like image 598
dragons Avatar asked Mar 02 '23 13:03

dragons


1 Answers

Update

Given the updated question, please have a look at this

jq '{props: [.props[] | (select(.property == "Hat") | del(.data["1234"])), select(.property != "Hat")]}'

Try it online!

This is just the jq expression itself. To run it on every file in a folder etc, just substitute this in the bash loop below.

How's this ...

jq 'delpaths([paths] | map(select(.[]=="1234")))'

First example

Input

{
    "data": {
        "1234": {
            "tt": true
        }
    }
}

Output

{
  "data": {}
}

Try it online!

Second Example

Input

{
    "data": {
        "1234": {
            "tt": true
        },
        "7890": {
            "tt": true
        }
    }
}

Output

{
  "data": {
    "7890": {
      "tt": true
    }
  }
}

Try it online!

A simple bash script to run this on every file (e.g. data-1.json) and save it in place ...

for file in *.json; do
    jq 'delpaths([paths] | map(select(.[]=="1234")))' <"$file" >"$file.new" && mv "$file.new" "$file"
done

That's as close as I can get without actual input/output instead of excerpts.

Hope this helps!

like image 165
Bean Taxi Avatar answered Mar 05 '23 16:03

Bean Taxi