Home > front end >  Transform specific fields into array(s) using jq
Transform specific fields into array(s) using jq

Time:04-22

Given the following JSON:

{
  "one": "1",
  "two": "2",
  "flag": "f1 f2 f3",
  "test one": "",
  "test two": "",
  "test three": ""
}

Is it possible to obtain the following result using jq?

{
  "one": "1",
  "two": "2",
  "flags": ["f1", "f2", "f3"],
  "tests": ["one", "two", "three"]
}

Three points are crucial:

  1. Leave unchanged any field that is not flag or starts with test

  2. Transform flag (space separated values) into an array

  3. Any field that starts with test is added to an array (tests) where the value is the remaining part of the field's name

CodePudding user response:

You can use /= to update by splitting, startswith to match at the beginnning of a string, and to_entries and with_entries to manipulate entries involving the key name:

jq '
  .flag /= " "
  | .tests = (to_entries | map(.key | select(startswith("test "))[5:]))
  | with_entries(select(.key | startswith("test ") | not))
'

Demo


Another, maybe more efficient implementation which loops just once through the object using reduce could be:

jq '
  reduce to_entries[] as {$key, $value} (null;
    if   $key == "flag"             then .flag = $value / " "
    elif $key | startswith("test ") then .tests  = [$key[5:]]
    else                                 .[$key] = $value end
  )
'

Demo


Given the sample data, both produce:

{
  "one": "1",
  "two": "2",
  "flag": [
    "f1",
    "f2",
    "f3"
  ],
  "tests": [
    "one",
    "two",
    "three"
  ]
}
  • Related