Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

filter certain (sub) keys from a JSON value

Tags:

json

jq

I have a relatively huge JSON file that contains lot of data that I do not need.

I would like to just keep the elements that are of interest for me but I want to keep the general structure.

[
  {
    "name"  : "foo",
    "age"   : 12,
    "weight": 23, 
    "colors": {
      "head":{
        "hair": "blue",
        "eyes": "green"
      }
    }
  },
  {
    "name"  : "bar",
    "age"   : 42,
    "weight": 54, 
    "colors": {
      "head":{
        "hair": "blue",
        "eyes": "blue"
      }
    }
  },
  {
    "name"  : "baz",
    "age"   : 65,
    "weight": 439, 
    "colors": {
      "head":{
        "hair": "green",
        "eyes": "red"
      }
    }
  }

]

The output should look like:

{
  "name": "foo",
  "colors": {
    "head": {
      "eyes": "green"
    }
  }
}
{
  "name": "bar",
  "colors": {
    "head": {
      "eyes": "blue"
    }
  }
}
{
  "name": "baz",
  "colors": {
    "head": {
      "eyes": "red"
    }
  }
}

My actual input object has ~100 leaf keys per top level object and I need ~10 and nearly all on different levels of the hierarchy.

I looked into some json processing APIs (e.g. javascript, lodash, and jq) and could not find such a mechanism. They mostly rely on creating new objects in plain syntax that require to construct the object from scratch.

Like:

jq '[.[]| {name: .name, colors:{head:{eyes: .colors.head.eyes}}}]'

with deep hierarchies this is a bit messy.

Did I miss something that either allows easier specifying deep objects keys like:

.[] | {name: .name, colors.head.eyes = .colors.head.eyes}

or some even more convenient: some sub key filter mechanism like

.[] | filteKeys(["name", "colors.head.eyes"])

I would prefer some command line able program, so I tried with JQ.

like image 917
vlad_tepesch Avatar asked Apr 25 '26 15:04

vlad_tepesch


1 Answers

some sub key filter mechanism can be implemented as follows.

def pick(paths):
  . as $in
  | reduce path(paths) as $path (null;
    setpath($path; $in | getpath($path))
  );

And you can use it like:

.[] | pick(.name, .colors.head.eyes)

demo at jqplay.org

like image 102
oguz ismail Avatar answered Apr 28 '26 19:04

oguz ismail



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!