Filter object by property and select with key in jmespath

Johannes Müller picture Johannes Müller · Jan 10, 2017 · Viewed 9.5k times · Source

I'm trying to filter properties of an object in jmespath based on the value of a subproperty and want to include only those properties where the subproperty is set to a specific value.

Based on this example data:

{
  "a": {
    "feature": {
      "enabled": true,
    }
  },
  "b": {
  },
  "c": {
    "feature": {
      "enabled": false
     }
  }
}

I'd like to get an object with all properties where the feature is enabled.

{
  "a": {
    "feature": {
      "enabled": true,
    }
  }
}

I figured I could use this jmespath query to filter the objects where property. enabled is set to true. Unfortunateley, it doesn't seem to work and instead returns an empty array.

*[?feature.enabled==`true`]

*.feature.enabled or *[feature.enabled] return just the boolean values without any context.

Even if *[?feature.enabled==true] would work, it would just be an array of the property values, but I need the keys (a and c) aswell. Is there any way to make this happen in jmespath?

This is all part of an ansible playbook, so there would certainly be a way to achieve selection in a different way (Jinja2 templates or custom plugin) but I wanted to try jmespath and would reason, that it should be capable of such a task.

Answer

techraf picture techraf · Sep 8, 2018

With dict2items filter in Ansible 2.5 and later, you can do it with:

- debug:
    msg: "{{ dict(my_data | dict2items | json_query('[?value.feature.enabled].[key, value]')) }}"

The result:

"msg": {
    "a": {
        "feature": {
            "enabled": true
        }
    }
}