JSON: Move Item's Key/Name into Attribute and Convert it to Array with jq
JSON (JavaScript Object Notation) is a commonly used data format for representing structured data. Arrays are one of the fundamental data structures in JSON, used to store a collection of similar items. Sometimes, you may encounter a JSON structure where the item's name or key is an essential piece of information that needs to be preserved. To address this, we can leverage the capabilities of jq, a command-line JSON processor, to reformulate the data into an array while incorporating the item's name as an attribute.
. as $arr | $arr
| keys # Get all keys (names) of the array
| map_values(
. as $item | {
item, # Preserve the original item
attribute: $item | keys # Move name to "attribute" property
}
)
This jq script effectively converts the input JSON object into an array of objects. Each object contains the original item as one property and an additional "attribute" property that captures the original key/name of the item. Here's how it works:
. as $arr
: This line assigns the input JSON object to a variable named$arr
, allowing us to manipulate it.$arr | keys
: It retrieves all the keys (or names) of the items in the array and stores them in a new array.map_values(...)
: This function iterates over each element in the array, accessing its value using.
. It applies the transformation defined within the curly braces{ ... }
to each item.. as $item | { ... }
: The.
refers to the current item being processed, and we assign it to a new variable$item
. Inside the curly braces, we define a new object with two properties:item
: This property retains the original item's value.attribute: $item | keys
: This property extracts the keys of the current item (which represent the names) and assigns them to the "attribute" property.
By utilizing this script, you can effectively restructure your JSON data, preserving essential information while converting it to an array of objects. This technique proves useful in various scenarios where you need to retain both the item's value and its associated name.
Alternate Approach Using to_entries
and from_entries
Another way to achieve a similar outcome is by utilizing to_entries
and from_entries
functions in jq. Here's the script:
Forward Transformation:
to_entries | map({name: .key} + .value)
Reverse Transformation:
map({key: .name, value: del(.name)}) | from_entries
Explanation:
to_entries
: This function converts the array into an array of key-value pairs, where each pair consists of the original key and the original item.map(...)
: It iterates over each key-value pair, allowing you to apply transformations.{name: .key} + .value
: Within the curly braces, a new object is created. It includes the "name" property set to the original key and the original item as a property with its original name.from_entries
: This function takes an array of key-value pairs and converts it back into an object, effectively reversing the transformation done byto_entries
.map({key: .name, value: del(.name)})
: For the reverse transformation, we extract the "name" and "value" properties from each object and remove the "name" property usingdel(.name)
.
This approach essentially converts the array of objects back into an object, preserving the item's value and key/name relationship.