Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

delete from one object those entries matching another object based off string id

So, given two files with JSON data from the same source type. The JSON objects look something like:

file1:

[
  {
    "data": {
      "id": "2",
      "nodes": [
        {
          "stuff": "foo"
        }
      ]
    }
  },
  {
    "data": {
      "id": "6",
      "nodes": [
        {
          "stuff": "bar"
        }
      ]
    }
  },
  {
    "data": {
      "id": "61",
      "nodes": [
        {
          "stuff": "baz"
        }
      ]
    }
  },
  {
    "data": {
      "id": "63",
      "nodes": [
        {
          "stuff": "qux"
        }
      ]
    }
  }
]

file2:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[
  {
    "data": {
      "id": "61",
      "nodes": [
        {
          "stuff": "baz"
        }
      ]
    }
  },
  {
    "data": {
      "id": "63",
      "nodes": [
        {
          "stuff": "qux"
        }
      ]
    }
  }
]

I’m trying to remove objects in the array in the first file with the matching IDs in the second file so that the resultant output would be:

[
  {
    "data": {
      "id": "2",
      "nodes": [
        {
          "stuff": "foo"
        }
      ]
    }
  },
  {
    "data": {
      "id": "6",
      "nodes": [
        {
          "stuff": "bar"
        }
      ]
    }
  }
]

I’ve tried a bunch of ways to accomplish this, but I haven’t found a proper solution yet.

A couple of attempts have been various permutations of the following with accompanying errors:

jq -n --argfile src /var/tmp/w-src.json --argfile dst /var/tmp/w-dst.json '
$dst
| [.data[].id] as $ids
| $src
| .data | map(select(.id | in($ids[])))

jq: error: select/0 is not defined at <top-level>, line 5:
| .data | map($ids | map(select .id == .))                         
jq: 1 compile error
jq -n --argfile src /var/tmp/w-src.json --argfile dst /var/tmp/w-dst.json '
$dst
| [.data[].id] as $ids
| $src
| .data[] | select(.id | in($ids[]))
'
jq: error (at <unknown>): Cannot check whether string has a string key

Ideally it would be super cool to do some kind of operation like:

$src.data[] - $dst.data[]

(kinda Ruby-ish like would be cool) and I admit, I haven’t tried this but I will for kicks and giggles.

I’m trying not to have to use a function and I want to accomplish this using jq. I’m probably not too far off, but I’m at a loss. Any thoughts?

>Solution :

You could compile a list of IDs from the second file using input, check against it using IN, and either use del to delete the matching, or map to keep those that do not match:

jq '
  (input | map(.data.id)) as $del | del(.[] | select(IN(.data.id; $del[])))
' file1.json file2.json

or

jq '
  (input | map(.data.id)) as $del | map(select(IN(.data.id; $del[]) | not))
' file1.json file2.json

If you can assert that objects with identical IDs also are identical in their other parts, and you don’t have many items (because it’s costly), you can even just subtract the second file from the first:

jq '. - input' file1.json file2.json
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading