Jq: select a subset of the keys to an object

Given the input json string of keys from the array, return an object only with elements that have keys in the source object and in the input array.

I have a solution, but I think it’s not elegant ( {($k):$input[$k]} feels especially awkward ...) and that this is a chance for me to find out.

 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 clear this?

I like Fetching selected properties from a nested JSON object using jq is a good starting place, but I can't get it to work.

+5
source share
5 answers

You can use this filter:

 with_entries( select( .key == ($keys | fromjson[]) ) ) 
+7
source

with internal verification:

 jq 'with_entries(select([.key] | inside(["key1", "key2"])))' 
+2
source

Jeff's answer has a couple of unnecessary inefficiencies, both of which are addressed as follows, assuming that --argjson keys are used instead of --arg keys :

 with_entries( select( .key as $k | $keys | index($k) ) ) 
+1
source

Here are some additional explanations.

For the input object {"key1":1, "key2":2, "key3":3} I would like to delete all keys that are not in the set of desired keys ["key1","key3","key4"]

  jq -n --argjson desired_keys '["key1","key3","key4"]' \ --argjson input '{"key1":1, "key2":2, "key3":3}' \ ' $input | with_entries( select( .key == ($desired_keys[]) ) )' 

with_entries converts {"key1":1, "key2":2, "key3":3} to the next array of key value pairs and displays the select statement in the array, and then returns the resulting array back to the object.

Here is the internal object in the with_entries .

 [ { "key": "key1", "value": 1 }, { "key": "key2", "value": 2 }, { "key": "key3", "value": 3 } ] 

we can select keys from this array that match our criteria.

The magic happens here ... look at what happens in the middle of this team. The following command takes an extended array of values ​​and turns them into a list of objects that we can select.

 jq -cn '{"key":"key1","value":1}, {"key":"key2","value":2}, {"key":"key3","value":3} | select(.key == ("key1", "key3", "key4"))' 

This will produce the following result:

 {"key":"key1","value":1} {"key":"key3","value":3} 

A recording command may be a little complicated, but it’s easy to remember that it accepts a filter and is defined as follows

 def with_entries(f): to_entries|map(f)|from_entries; 

This is the same as

 def with_entries(f): [to_entries[] | f] | from_entries; 

Another part of the question that confuses people is the multiple matches on the right ==

Consider the following command. We see that the output is an external production of all left lists and right lists.

 jq -cn '1,2,3| . == (1,1,3)' true true false false false false false false true 

If this predicate is in the select statement, we save the input when the predicate is true. Please note that you can also duplicate input.

 jq -cn '1,2,3| select(. == (1,1,3))' 1 1 3 
0
source

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

use the in operator if exact match is needed: for example, this will only select .key2 and .key12

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

because the in operator checks the key only from the object (or the index exists? from the array), here it must be written in the syntax of the object with the desired keys as keys, but the values ​​do not matter; use in a statement is not ideal for this purpose, I would like Javascript ES6 to include a reverse version of the API, which should 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"])))' 

is there an included? for checking the .key element included? from array

0
source

All Articles