用于展平对象数组的 JMESPath 表达式,每个对象都具有嵌套的对象数组

Ale*_*mer 8 json ansible jmespath

我有包含数据库数组的 JSON,每个数据库都有一个用户数组,例如

{"databases": [
  {"db": "db_a", "users": [{"name": "alice"}, {"name": "alex"}]},
  {"db": "db_b", "users": [{"name": "bob"}, {"name": "brienne"}]}
]}
Run Code Online (Sandbox Code Playgroud)

我想生成一个数据库和用户的平面数组,即

[
  {"db": "db_a", "name": "alice"},
  {"db": "db_a", "name": "alex"},
  {"db": "db_b", "name": "bob"},
  {"db": "db_b", "name": "brienne"}
]
Run Code Online (Sandbox Code Playgroud)

在 SQL 术语中,这将是笛卡尔连接或笛卡尔积,但我不确定树结构中的正确术语。到目前为止我最接近的是

databases[].users[]
Run Code Online (Sandbox Code Playgroud)

产生

databases[].users[]
Run Code Online (Sandbox Code Playgroud)

databases[].{db: db, name: users[].name}
Run Code Online (Sandbox Code Playgroud)

产生

[{"name": "alice"}, {"name": "alex"}, {"name": "bob"}, {"name": "brienne"}]
Run Code Online (Sandbox Code Playgroud)

附录:我很高兴接受“你不能用 JMESPath 做到这一点,这就是原因......”作为答案。HN 评论` `暗示了这一点

进行迭代时无法引用父级。为什么?迭代、[*] 和映射的所有选项都使用迭代项作为任何表达式的上下文。没有机会获得任何其他值

Cal*_*pin 1

从 JEP 18 开始,您可以使用PyPI 上提供的let 表达式jmespath-community

let 表达式引入了词法作用域,并允许您绑定在给定词法作用域的上下文中计算的变量。这使得查询可以引用在当前元素之外定义的元素

databases[*].let $db = db in users[*].{"db": $db, "name": name}
Run Code Online (Sandbox Code Playgroud)

这会产生

databases[*].let $db = db in users[*].{"db": $db, "name": name}
Run Code Online (Sandbox Code Playgroud)

正如 Alex Willmer 所指出的,你可以用以下方法将其展平

(databases[*].let $db = db in users[(].{"db": $db, "name": name})[]
Run Code Online (Sandbox Code Playgroud)

生产

[
  [
    {"db": "db_a", "name": "alice"},
    {"db": "db_a", "name": "alex"}
  ],
  [
    {"db": "db_b", "name": "bob"},
    {"db": "db_b", "name": "brienne"}
  ]
]
Run Code Online (Sandbox Code Playgroud)