Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping two json with jq and script bash

Tags:

json

bash

shell

jq

I have a json file list_values.json with array of json with an "origine" field :

[
        {
          "origine": "reason1",
          "identifiant": "1234_AAA"
        },
        {
          "origine": "reason3",
          "identifiant": "5678_BBB"
        }
]

I have mapping.json file with a list of predefined fields :

{
  "REASON_0": "reason0",
  "REASON_1": "reason1",
  "REASON_2": "reason2",
  "REASON_3": "reason3",
  "REASON_4": "reason4"
}

I wrote a bash script using jq with this line :

jq '.[] |= . + {"type": (.identifiant | split("_") | .[1] )}' list_values.json > add_fields.json

My file add_fields.json :

[
        {
          "origine": "reason1",
          "identifiant": "1234_AAA",
          "type": "AAA"
        },
        {
          "origine": "reason3",
          "identifiant": "5678_BBB",
          "type": "BBB"
        }
]

I would like to add a "reason" field equal to the key of mapping.json whose value matches the "origine" field of list_values.json. Like this :

[
        {
          "origine": "reason1",
          "identifiant": "1234_AAA",
          "type": "AAA",
          "reason": "REASON_1"
        },
        {
          "origine": "reason3",
          "identifiant": "5678_BBB",
          "type": "BBB",
          "reason": "REASON_3"
        }
]

What can I do this with jq ?

I specify that the values of mapping.json are unique as the keys.

like image 997
Sam Avatar asked Feb 13 '26 13:02

Sam


2 Answers

The following looks understandable and extensible: it first builds a lookup object (with INDEX) and then maps each input object to a new object with the added properties:

jq 'INDEX(input|to_entries[]; .value) as $mapping
| map(
  .type=(.identifiant/"_"|last)
  | .reason=$mapping[.origine].key
)' list_values.json mapping.json

Alternatively, merge an object with the new properties into the existing items of the array:

jq 'INDEX(input|to_entries[]; .value) as $mapping
| .[]
|= . + {
  type: (.identifiant / "_" | last),
  reason: $mapping[.origine].key
}' list_values.json mapping.json

Output:

[
  {
    "origine": "reason1",
    "identifiant": "1234_AAA",
    "type": "AAA",
    "reason": "REASON_1"
  },
  {
    "origine": "reason3",
    "identifiant": "5678_BBB",
    "type": "BBB",
    "reason": "REASON_3"
  }
]
like image 174
knittl Avatar answered Feb 15 '26 07:02

knittl


With jq 1.6+ you can use JOIN to get the matchings. To this end, you need to flip keys and values for the index (in the mappings object). In doing so, you can already insert the "reason" field name, which makes it easier to just add the results afterwards:

jq '[JOIN(
  input | with_entries({key: .value, value: {reason: .key}});
  .[] | .type = (.identifiant | split("_")[1]);
  .origine;
  add
)]' list_values.json mapping.json
[
  {
    "origine": "reason1",
    "identifiant": "1234_AAA",
    "type": "AAA",
    "reason": "REASON_1"
  },
  {
    "origine": "reason3",
    "identifiant": "5678_BBB",
    "type": "BBB",
    "reason": "REASON_3"
  }
]
like image 40
pmf Avatar answered Feb 15 '26 06:02

pmf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!