skip to Main Content

I have the following JSON structure:

[
 {
   "key11": "value11",
   "key12": "value12",
   "key13": "value13",
   "key14": "value14"
 },
 {
   "key21": "value21",
   "key22": "value22",
   "key23": "value23",
   "key24": "value24"
 },
 {
   "key31": "value31",
   "key32": "value32",
   "key33": "value33",
   "key34": "value34"
 }
]

How do I convert it to the following structure:

{
  "value11": "value12",
  "value21": "value22", 
  "value31": "value32"
}

I have tried a few JQ operators, but nothing seems to work.

3

Answers


  1. let data = [
        {
          "key11": "value11",
          "key12": "value12",
          "key13": "value13",
          "key14": "value14"
        },
        {
          "key21": "value21",
          "key22": "value22",
          "key23": "value23",
          "key24": "value24"
        },
        {
          "key31": "value31",
          "key32": "value32",
          "key33": "value33",
          "key34": "value34"
        }
       ];
       
       //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
       let result = data.reduce((acc,next) => {
            let [first_val,second_val] = Object.values(next);
            acc[first_val] = second_val;
            return acc;
       },{});
    
       console.log(JSON.stringify(result));
    
    Login or Signup to reply.
  2. is there an option to use a string as index instead of a numeric index?

    Yes, you could, for example, read the string keys as arguments, and resolve them in an iterative (or mapping) context.

    One way would be to reduce the input into an initially empty output object {}, using the key of to_entries to access the iteration index, which in turn can be used to index into the argument list:

    jq 'reduce to_entries[] as {$key, $value} ({};
      $ARGS.positional[$key *2:] as [$k, $v] | .[$value[$k]] = $value[$v]
    )' input.json --args key11 key12 key21 key22 key31 key32
    

    With this effort, however, you could also just map the input array, and use from_entries to generate the output object, enabling you to use the with_entries shortcut:

    jq 'with_entries(
      $ARGS.positional[.key *2:] as [$k, $v] | {key:.value[$k], value:.value[$v]}
    )' input.json --args key11 key12 key21 key22 key31 key32
    
    Login or Signup to reply.
  3. I’m sorry, my initial JSON structure was wrong: Each object in the array has the same keys.

    So, assuming your input with all objects having the same keys looks like

    [
      {
        "key1": "value11",
        "key2": "value12",
        "key3": "value13",
        "key4": "value14"
      },
      {
        "key1": "value21",
        "key2": "value22",
        "key3": "value23",
        "key4": "value24"
      },
      {
        "key1": "value31",
        "key2": "value32",
        "key3": "value33",
        "key4": "value34"
      }
    ]
    

    Then, you could either use map to turn each array item to a single-field object, and then add to combine these objects into one (Demo):

    jq 'map({(.key1): .key2}) | add' input.json
    

    Or you could reduce the array’s items into an initially empty output object {} by iteratively setting another of its keys (Demo):

    jq 'reduce .[] as $i ({}; .[$i.key1] = $i.key2)' input.json
    

    Both approaches return:

    {
      "value11": "value12",
      "value21": "value22",
      "value31": "value32"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search