json - 用于展平对象数组的 JMESPath 表达式,每个对象都有嵌套的对象数组
问题描述
我有一个包含数据库数组的 JSON,每个数据库都有一个用户数组,例如
{"databases": [
{"db": "db_a", "users": [{"name": "alice"}, {"name": "alex"}]},
{"db": "db_b", "users": [{"name": "bob"}, {"name": "brienne"}]}
]}
我想生成一个平面的数据库和用户数组,即
[
{"db": "db_a", "name": "alice"},
{"db": "db_a", "name": "alex"},
{"db": "db_b", "name": "bob"},
{"db": "db_b", "name": "brienne"}
]
在 SQL 术语中,这将是笛卡尔连接或笛卡尔积,但我不确定树结构中的正确术语。到目前为止我最接近的是
databases[].users[]
产生
[{"name": "alice"}, {"name": "alex"}, {"name": "bob"}, {"name": "brienne"}]
和
databases[].{db: db, name: users[].name}
产生
[
{"db": "db_a", "name": ["alice", "alex"]},
{"db": "db_b", "name": ["bob", "brienne"]}
]
附录:我很高兴接受“你不能用 JMESPath 做到这一点,这就是为什么......”作为答案。HN 评论“暗示了这一点
进行迭代时无法引用父母。为什么?迭代的所有选项 [* ] 和 map 都使用迭代项作为任何表达式的上下文。没有机会获得任何其他价值
解决方案
您不能仅使用 JMESPath 执行此操作,因为 JMESPath 表达式只能引用单个范围。当当前范围是用户对象时,无法到达外部范围(数据库对象)。JEP 11将允许访问其他范围,但几年后仍未被接受。
在 Ansible 上,它可以用其他过滤器(h/t Vladimir)完成,还有一些丑陋
databases_users: "{{
databases | subelements('users')
| to_json | from_json
| json_query('[*].{db: [0].db, name: [1].name}')
}}"
解释
提醒一下,我们的出发点是
[ {"db": "db_a", "users": [{"name": "alice"}, {"name": "alex"}]},
...]
过滤器将其subelements
转换为 Python 元组对列表
[ ({"db": "db_a", "users": [{"name": "alice"}, {"name": "alex"}]},
{"name": "alice"}),
...]
to_json
并将from_json
元组对转换为列表(Python 的 JMESPath 忽略元组)
[ [{"db": "db_a", "users": [{"name": "alice"}, {"name": "alex"}]},
{"name": "alice"}],
...]
json_query
选择所需db
的user
值
[ {"db": "db_a", "name": "alice"},
...]
推荐阅读
- ansible - 如何从 Gitlab-CI 运行 Ansible-Playbook?
- javascript - 满足条件时如何将值从映射函数内部推送到对象?
- javascript - 如何轮换代理(在列表内)
- reactjs - `react-select` 动态添加新值
- python - 如何在 PyQt5 中对齐小部件
- angular - 为什么 Ngx-leaflet-draw 工具栏没有出现?
- typescript - 泛型类型作为函数返回类型
- azure - 如何将 Azure 平台日志数据保留在存储帐户中超过 365 天?
- unity3d - 如何在统一中连续创建生成器
- javascript - VueJS 反应性:用数据替换数组