6

I have the following object

{
  "name": "Papanito",
  "fields": [
    {
      "name": "Name1",
      "value": "Value1",
      "type": 0,
      "linkedId": null
    },
    {
      "name": "Name2",
      "value": "Value2",
      "type": 0,
      "linkedId": null
    },
    {
      "name": "Name3",
      "value": "Value3",
      "type": 0,
      "linkedId": null
    },
    {
      "name": "Name4",
      "value": "Value3",
      "type": 0,
      "linkedId": null
    }
  ],
}

Which I would like to convert in this

{
  "name": "Papanito",
  "fields": [
    "Name1": "Value1",
    "Name2": "Value2",
    "Name3": "Value3",
    "Name4": "Value4",
  ],
}

I tried several things, but I did not yet figure out how to do that.

1 Answer 1

4
jq '.fields |= ( map(.key = .name | del(.type,.linkedId,.name)) | from_entries )' file

This updates the fields array. First, for each element (using map()), a key key is created with the value from the name key. Then the type, linkedId, and name keys are deleted from the element. We are now left with a key and a value key in each element of the fields array, which is just what from_entries needs to associate the key values as keys to the value values.

Testing on the data given in the question (with a trailing comma removed), this generates the following JSON:

{
  "name": "Papanito",
  "fields": {
    "Name1": "Value1",
    "Name2": "Value2",
    "Name3": "Value3",
    "Name4": "Value3"
  }
}

Note that your expected output is invalid JSON, as an array can't have keys. Therefore, the fields value in the output above is an object, not an array.

Would you want to keep fields as an array, you could rearrange the operations a bit:

jq '.fields |= map([.key = .name | del(.type,.linkedId,.name)] | from_entries)' file

For the given data (corrected as mentioned above), this would generate something equivalent to the following document:

{
   "name": "Papanito",
   "fields": [
      { "Name1": "Value1" },
      { "Name2": "Value2" },
      { "Name3": "Value3" },
      { "Name4": "Value3" }
   ]
}

This has the benefit that two elements with the same original name values would not overwrite each other in the result.


Conceptually, the above deletes the data that we no longer want. The following variations extract the data we want instead.

This generates the last result from above:

jq '.fields |= map({ (.name): .value })' file

And we can get the first result (with fields as a single object) by merging the entries in the list:

jq '.fields |= (map({ (.name): .value }) | add)' file
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .