jsonselectkeysubsetjq

jq: selecting a subset of keys from an object


Given an input json string of keys from an array, return an object with only the entries that had keys in the original object and in the input array.

I have a solution but I think that it isn't elegant ({($k):$input[$k]} feels especially clunky...) and that this is a chance for me to learn.

jq -n '{"1":"a","2":"b","3":"c"}'   \
    | jq --arg keys '["1","3","4"]' \
    '. as $input 
     | ( $keys | fromjson )
     | map( . as $k
          | $input
          | select(has($k))
          | {($k):$input[$k]}
          )
     | add'

Any ideas how to clean this up?

I feel like Extracting selected properties from a nested JSON object with jq is a good starting place but i cannot get it to work.


Solution

  • the inside operator works for most of time; however, I just found the inside operator has side effect, sometimes it selected keys not desired, suppose input is { "key1": val1, "key2": val2, "key12": val12 } and select by inside(["key12"]) it will select both "key1" and "key12"

    use the in operator if need an exact match: like this will select .key2 and .key12 only

    jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'
    

    because the in operator checks key from an object only (or index exists? from an array), here it has to be written in an object syntax, with desired keys as keys, but values do not matter; the use of in operator is not a perfect one for this purpose, I would like to see the Javascript ES6 includes API's reverse version to be implemented as jq builtin

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

    jq 'with_entries(select(.key | included(["key2", "key12"])))'
    

    to check an item .key is included? from an array