berisa
berisa

Reputation: 13

filter json when it must fulfill two conditions. One for the key, and one in a nested array for the selected element with jq

given the following json, how the below code should be altered, so as to add a new condition.

return all ids, that have an element that starts with 4, but also have an array that has in it either the

"v" value, or the "9" value.

Input json:

{
  "memo": {
    "notice": "delivered on 17"
  },
  "message": "{\"id\":\"1\",\"401\":[[\" 0\",[\"a\",\"UK\"],[\"b\",\"Euy/ O\"],[\"c\",\"20160811\"],[\"g\",\"R2\"]],[\" 1\",[\"a\",\"UK\"],[\"b\",\"LO\"],[\"c\",\"20160811\"]]]}"
}
{
  "memo": {
    "notice": "delivered on 190"
  },
  "message": "{\"id\":\"2\",\"424\":[[\" 0\",[\"v\",\"UK\"],[\"9\",\"Euy/ O\"],[\"c\",\"20160811\"],[\"g\",\"R2\"]],[\" 1\",[\"a\",\"UK\"],[\"b\",\"LO\"],[\"c\",\"20160811\"]]]}"
}
{
  "memo": {
    "notice": "delivered on 734"
  },
  "message": "{\"id\":\"3\",\"432\":[[\" 0\",[\"a\",\"UK\"],[\"9\",\"Euy/ O\"],[\"c\",\"20160811\"],[\"v\",\"R2\"]],[\" 1\",[\"a\",\"UK\"],[\"b\",\"LO\"],[\"c\",\"20160811\"]]]}"
}
{
  "memo": {
    "notice": "delivered on 1092"
  },
  "message": "{\"id\":\"888\",\"532\":[[\" 0\",[\"v\",\"UK\"],[\"b\",\"Euy/ O\"],[\"c\",\"20160811\"],[\"g\",\"R2\"]],[\" 1\",[\"a\",\"UK\"],[\"b\",\"LO\"],[\"c\",\"20160811\"]]]}"
}

snippet that needs to be adjusted:
< input.json jq -r '.content
    | fromjson
    | select( any(keys_unsorted[]; test("^4")) )
    | .["id"]'

Desired output:

2
3

jq version: 1.6, already tried without success to use:

  1. index
  2. the built-in IN statement

We need only the 001 values, of each json object, that has an element which starts with a 4, and that this element (say 401) also has a value of v, or 9 in its nested array, or both v and 9.

Upvotes: 0

Views: 81

Answers (1)

peak
peak

Reputation: 116670

First, the relevant key is .message, not .content.

Second, since you are imposing an additional condition, you have only to use and.

Third, the requirements are a bit ambiguous, but the following produces the expected results, and is a solution to one disambiguation of the stated problem:

.message
    | fromjson
    | select( any(keys_unsorted[]; test("^4")) 
              and (.[] | arrays | flatten | (index(["v"]) or index(["9"])) )  )
    | .["id"]

As you suggest, you could also use IN.

Upvotes: 1

Related Questions