按属性过滤对象,并使用jmespath中的键选择

时间:2017-01-10 22:30:14

标签: json ansible normalization jmespath

我尝试根据子属性的值过滤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并且会推理,它应该能够这样做一项任务。

3 个答案:

答案 0 :(得分:6)

抱歉,AFAIK在原生JMESPath中这是不可能的 在jq中的to_entries等不同工具中,可以使用自定义内置函数 对于jmespath.py,因此对于Ansible,挂起pull request来实现键操作。

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

答案 1 :(得分:5)

使用Ansible 2.5及更高版本中的dict2items过滤器,您可以执行以下操作:

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

结果:

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

答案 2 :(得分:0)

简短回答(TL; DR)

  • 实际上,是的,仅通过本机jmespath就可以做到这一点
  • 问题在于,针对源数据集的查询将非常麻烦,因为对于这种通用的jmespath查询,源数据集被标准化较差

示例

  

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

[
  {
      "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中完全可行,但这会很痛苦。

另请参见