简体   繁体   中英

Conditional transform of JSON value based on key and type with jq

I have a json file where I'd like to transform the value of some named keys from numeric ( 0 / 1 ) to boolean ( 0 => false , 1 => true ) using jq .

The transform should be re-entrant. If I run it on a (partially) transformed file, already converted keys should stay the same.

Given this json file:

{
  "foo": {
    "bar": {
      "color": "green",
      "visible": 0
    },
    "baz": {
      "fruit": "banana",
      "tasty": true
    }
  },
  "fubar": {
    "string": "hi",
    "value": "world",
    "enabled": 1,
    "sub": {
      "valuable": true,
      "empty": false
    }
  },
  "running": 1
}

and the following list of keys:

  • .foo.bar.visible
  • .foo.baz.tasty
  • .fubar.enabled
  • .fubar.sub.empty
  • .running

I'd like jq to transform the above into this:

{
  "foo": {
    "bar": {
      "color": "green",
      "visible": false
    },
    "baz": {
      "fruit": "banana",
      "tasty": true
    }
  },
  "fubar": {
    "string": "hi",
    "value": "world",
    "enabled": true,
    "sub": {
      "valuable": true,
      "empty": false
    }
  },
  "running": true
}

I've come up with this (using the first two keys only to keep it short):

cat in.json | jq '.foo.bar.visible = (if .foo.bar.visible | type == "boolean" then .foo.bar.visible elif .foo.bar.visible == 1 then true else false end) | .foo.baz.tasty = (if .foo.baz.tasty | type == "boolean" then .foo.baz.tasty elif .foo.baz.tasty == 1 then true else false end)' > out.json

but there has to be a better way?

Also tried to put it into a def but that didn't work:

def numerictobool(key):
  $key = (if $key | type == "boolean" then $key elif $key == 1 then true else false end)
numerictobool(.network.eth0.enabled)
def numerictobool:
  if type == "boolean" then . else . == 1 end;

.
| .foo.bar.visible |= numerictobool
| .foo.baz.tasty |= numerictobool
| .fubar.enabled |= numerictobool
| .fubar.sub.empty |= numerictobool
| .running |= numerictobool

...emits as output, given your input:

{
  "foo": {
    "bar": {
      "color": "green",
      "visible": false
    },
    "baz": {
      "fruit": "banana",
      "tasty": true
    }
  },
  "fubar": {
    "string": "hi",
    "value": "world",
    "enabled": true,
    "sub": {
      "valuable": true,
      "empty": false
    }
  },
  "running": true
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM