Search code examples
jsonpathjmespathobjectpath

Filter JSON object based on children keys


I am trying to find a procedural way of applying the following filter. Given the following object, how can I get all top-level keys that contain child c2?

{
  "a1" : {
    "b" : {
      "c1": {},
      "c2": {}
    }
  },
  "a2" : {
    "b" : {
      "c1" : {}
    }
  },
  "a3" : {
    "b" : {
      "c1" : {},
      "c2" : {}
    }
  } 
}

Expected result:

["a1", "a3"]

I need that filter in JSONPath, JMESPath or ObjectPath syntax.

I tried countless combinations of $.*[@.b.c2] in ObjectPath, things like $..[?(b.c2)] in JSONPath, down to constructs like @.* | [?contains(keys(@), 'c2')] or @.*[b.c2] | @ in JMESPath - all to no avail.


Solution

  • In ObjectPath selectors work only on lists so $.*[@.b.c2] has nothing to work on. Nested objects like in your example are rare so I didn't implement a way to do what you need. You could try to transform your object to an array like following:

    [
      {
        "name": "a1",
        "b": {
          "c1": {},
          "c2": {}
        }
      },
      {
        "name": "a2",
        "b": {
          "c1": {}
        }
      },
      {
        "name": "a3",
        "b": {
          "c1": {},
          "c2": {}
        }
      }
    ]

    and then use selectors.

    $.*[@.b.c2 is not null].name

    PS. Use the newest ObjectPath version from Github. I fixed some issues with null comparison just a minute ago.