Jordi
Jordi

Reputation: 23277

jq: filter nested array objects

Here my documents:

[
  {
    "id": "3e67b455-8cdb-4bc0-a5e1-f90253870fc9",
    "identifier": [
      {
        "system": {
          "value": "urn:oid:2.16.724.4.9.20.91-INVENTAT"
        },
        "value": {
          "value": "04374"
        }
      },
      {
        "system": {
          "value": "urn:oid:2.16.724.4.9.20.2-INVENTAT"
        },
        "value": {
          "value": "INFP3"
        }
      },
      {
        "system": {
          "value": "urn:oid:INVENTAT"
        },
        "value": {
          "value": "CBOU035"
        }
      }
    ]
  },
  {
    "id": "0f22e5ff-70bc-457f-bdaf-7afe86d478de",
    "identifier": [
      {
        "system": {
          "value": "urn:oid:2.16.724.4.9.20.91-INVENTAT"
        },
        "value": {
          "value": "04376"
        }
      },
      {
        "system": {
          "value": "urn:oid:2.16.724.4.9.20.2-INVENTAT"
        },
        "value": {
          "value": "INF07"
        }
      },
      {
        "system": {
          "value": "urn:oid:INVENTAT"
        },
        "value": {
          "value": "S527918"
        }
      }
    ]
  },
  {
    "id": "a1ea574c-438b-443c-ad87-d31d09d581f0",
    "identifier": [
      {
        "system": {
          "value": "urn:oid:2.16.724.4.9.20.91-INVENTAT"
        },
        "value": {
          "value": "08096"
        }
      },
      {
        "system": {
          "value": "urn:oid:2.16.724.4.9.20.2-INVENTAT"
        },
        "value": {
          "value": "INF04"
        }
      },
      {
        "system": {
          "value": "urn:oid:INVENTAT"
        },
        "value": {
          "value": "5635132"
        }
      }
    ]
  }
]

I need to filter .identifier where system.value="urn:oid:2.16.724.4.9.20.91-INVENTAT" or system.value="urn:oid:2.16.724.4.9.20.2-INVENTAT" and pick .value.value.

Desired output:

[
  {
    "id": "3e67b455-8cdb-4bc0-a5e1-f90253870fc9",
    "oid1": "04374",
    "oid2": "INFP3"
  },
  {
    "id": "0f22e5ff-70bc-457f-bdaf-7afe86d478de",
    "oid1": "04376",
    "oid2": "INF07"
  },
  {
    "id": "a1ea574c-438b-443c-ad87-d31d09d581f0",
    "oid1": "08096",
    "oid2": "INF04"
  }
]

I've tried:

map(
    {
        id,
        oid1: select(.identifier?[]?.system.value == "urn:oid:2.16.724.4.9.20.91-INVENTAT") | .identifier[].value.value,
        oid2: select(.identifier?[]?.system.value == "urn:oid:2.16.724.4.9.20.2-INVENTAT") | .identifier[].value.value
    }
)

But output is not what I need: you can find it on this jqplay.

Any ideas?

Upvotes: 1

Views: 221

Answers (2)

dawg
dawg

Reputation: 104102

Here is a ruby to do that:

ruby -r json -e '
def walk(x, filt)
    rtr=[]
    rep=["uab", "ub"]
    x.each{|e| 
        rd={"id"=>e["id"]}.merge(
        e["identifier"].
            filter{|ea| filt.include?(ea["system"]["value"])}.
            map.with_index(1){|di, i| ["#{rep[i%2]}", "#{di["value"]["value"]}"]}.to_h)
        rtr << rd       
        }
    rtr
end
    
data=JSON.parse($<.read)
puts walk(data, ["urn:oid:2.16.724.4.9.20.91-INVENTAT", "urn:oid:2.16.724.4.9.20.2-INVENTAT"]).to_json
' file 

Prints:

[{"id":"3e67b455-8cdb-4bc0-a5e1-f90253870fc9","ub":"04374","uab":"INFP3"},{"id":"0f22e5ff-70bc-457f-bdaf-7afe86d478de","ub":"04376","uab":"INF07"},{"id":"a1ea574c-438b-443c-ad87-d31d09d581f0","ub":"08096","uab":"INF04"}]

Upvotes: 0

pmf
pmf

Reputation: 36646

This uses IN to check for your query strings, and with_entries on an array to generate the indeces for the oid keys.

jq '
  map({id} + (.identifier | map(select(IN(.system.value; 
    "urn:oid:2.16.724.4.9.20.91-INVENTAT",
    "urn:oid:2.16.724.4.9.20.2-INVENTAT"
  )).value.value) | with_entries(.key |= "oid\(. + 1)")))
'
[
  {
    "id": "3e67b455-8cdb-4bc0-a5e1-f90253870fc9",
    "oid1": "04374",
    "oid2": "INFP3"
  },
  {
    "id": "0f22e5ff-70bc-457f-bdaf-7afe86d478de",
    "oid1": "04376",
    "oid2": "INF07"
  },
  {
    "id": "a1ea574c-438b-443c-ad87-d31d09d581f0",
    "oid1": "08096",
    "oid2": "INF04"
  }
]

Demo

Upvotes: 2

Related Questions