skip to Main Content

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.

2

Answers


  1. 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"
      }
    ]
    
    Login or Signup to reply.
  2. 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"
      }
    ]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search