21

我正在尝试根据子属性的值过滤jmespath中对象的属性,并且只想包含子属性设置为特定值的那些属性。

基于此示例数据:

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

我想获得一个具有启用该功能的所有属性的对象。

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

我想我可以使用这个 jmespath 查询来过滤property. enabled设置为 true 的对象。不幸的是,它似乎不起作用,而是返回一个空数组。

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

*.feature.enabled*[feature.enabled]仅返回布尔值而无需任何上下文。

即使*[?feature.enabled==true]可以工作,它也只是属性值的数组,但我也需要键(ac)。有没有办法在 jmespath 中实现这一点?

这都是 ansible playbook 的一部分,所以肯定有一种方法可以以不同的方式(Jinja2 模板或自定义插件)实现选择,但我想尝试 jmespath 并且认为它应该能够完成这样的任务。

4

4 回答 4

10

使用dict2itemsAnsible 2.5 及更高版本中的过滤器,您可以这样做:

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

结果:

"msg": {
    "a": {
        "feature": {
            "enabled": true
        }
    }
}
于 2018-09-08T08:16:26.893 回答
8

抱歉,但是 AFAIK 这在本机 JMESPath 中是不可能的。在jq
等不同的工具中有用于此目的的自定义内置函数。 对于Ansible 来说,有挂起的拉取请求来实现键操作。to_entries
jmespath.py

更新:我制作了json_query过滤器的补丁版本。
有关其他信息,请参阅答案。

于 2017-01-11T07:20:00.567 回答
5

简答(TL;DR)

  • 实际上,是的,这仅靠本机 jmespath 是可能的
  • 问题是,对源数据集的查询将非常麻烦,因为对于这种通用 jmespath 查询,源数据集的标准化很差。

例子

以下(太长)jmespath 查询针对 OP 中的源数据...

[
  {
      "item_key":           `a`
      ,"feature_enabled":   @.a.feature.enabled
      ,source_object:       @.a
  }
  ,{
      "item_key":           `b`
      ,"feature_enabled":   @.b.feature.enabled
      ,source_object:       @.b
  }
  ,{
      "item_key":           `c`
      ,"feature_enabled":   @.c.feature.enabled
      ,source_object:       @.c
  }
]|[? feature_enabled == `true`]

...产生以下结果

[
  {
    "item_key": "a",
    "feature_enabled": true,
    "source_object": {
      "feature": {
        "enabled": true
      }
    }
  }
]

这与所需的输出相同或基本相似,但我们必须弯曲大脑才能到达那里的事实表明我们正试图迫使一个方形钉穿过一个圆孔。

陷阱

这个 jmespath 查询看起来如此冗长和繁琐的原因是源数据集本身对于通用 jmespath 查询的标准化很差。

这是因为它使用对象键作为顶级排序方法,而顺序索引列表就足够了。

每当您有一个可能包含任意数量值的数据集时,几乎总是最好使用序列进行顶级排序,而不是对象键。

如果您发现您可以在 jmespath 中执行某些操作,但是每当您将另一个“条目”添加到“任意(非固定)长度的条目集”中时,您都必须修改您的 jmespath 查询,您是在与 Jmespath 作斗争而不是使用它.

每当您看到使用 Jmespath 似乎“不可能完成”的查询时,您几乎肯定是在处理使用序列可能更合适的对象的数据结构。

对象键通常意味着固定数量的属性,jmespath 可以处理得很好。

即使是任意深度嵌套的对象属性也很好,只要这些对象属性不被用作顺序枚举的替代品。

当您发现必须创建对象序列以绕过对象对象时,事情只会开始变得不舒服……这在 jmespath 中完全可行,但会很痛苦。

也可以看看

于 2019-03-23T04:55:18.883 回答
0

您可以使用:

<json_data>|[*]|[? @.feature.enabled]
于 2022-02-09T13:40:32.820 回答