简体   繁体   中英

How to swap key and value of an object using jq?

Using jq I would like to inverse a json object so that the property becomes the value and the value becomes the key.

Source:

{ 
    "123": "Foobar"
    "567": "Poit"
} 

Goal:

{ 
    "Foobar": "123"
    "Poit": "567"
} 

How can I achieve that?

In your particular case:

to_entries | map( {(.value) : .key } ) | add

More robustly:

to_entries | map( {(.value|tostring) : .key } ) | add

Or if you prefer:

with_entries( .key as $k | .key = (.value|tostring) | .value = $k )

Caveat: all these are potentially lossy.

If some keys have equal values then probably you would like to get an array of keys as value:

to_entries
| map( {(.value) : {(.key):null} } )
| reduce .[] as $item ({}; . * $item)
| to_entries
| map({key:.key, value:(.value|keys)})
| from_entries

input:

{
  "key1": "val0",
  "key2": "val1",
  "key3": "val1"
}

output:

{
  "val0": ["key1"],
  "val1": ["key2", "key3"]
}

I would use an approach similar to @peak's answer but without using the add method

First use to_entries to get an output like this:

-> to_entries
Output:
[
  {
    "key": "123",
    "value": "Foobar"
  },
  {
    "key": "567",
    "value": "Poit"
  }
]

Then use map to swap the keys with values:

-> to_entries | map({key: .value|tostring, value: .key})  ###**tostring** method converts a number to string since keys can't be numbers
Output:
[
  {
    "key": "Foobar",
    "value": "123"
  },
  {
    "key": "Poit",
    "value": "567"
  }
]

Finally use from_entries to remove the key/value and return back to the original format:

-> to_entries | map({key: .value|tostring, value: .key}) | from_entries
Output:
{
  "Foobar": "123",
  "Poit": "567"
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM