使用 Ansibles uri 模块从非平凡 JSON 解析值

Parsing value from non-trivial JSON using Ansibles uri module

我有这个(在所示的示例中,我通过删除许多行来减少它)从 Spark 服务器检索到的非平凡 JSON:

{
  "spark.worker.cleanup.enabled": true,
  "spark.worker.ui.retainedDrivers": 50,
  "spark.worker.cleanup.appDataTtl": 7200,
  "fusion.spark.worker.webui.port": 8082,
  "fusion.spark.worker.memory": "4g",
  "fusion.spark.worker.port": 8769,
  "spark.worker.timeout": 30
}

我尝试阅读 fusion.spark.worker.memory 但没能读懂。在我的调试语句中,我可以看到信息在那里:

msg: "Spark memory: {{spark_worker_cfg.json}} 显示:

ok: [process1] => {
    "msg": "Spark memory: {u'spark.worker.ui.retainedDrivers': 50, u'spark.worker.cleanup.enabled': True, u'fusion.spark.worker.port': 8769, u'spark.worker.cleanup.appDataTtl': 7200, u'spark.worker.timeout': 30, u'fusion.spark.worker.memory': u'4g', u'fusion.spark.worker.webui.port': 8082}"
}

使用 var: spark_worker_cfg 的转储显示如下:

ok: [process1] => {
    "spark_worker_cfg": {
        "changed": false,
        "connection": "close",
        "content_length": "279",
        "content_type": "application/json",
        "cookies": {},
        "cookies_string": "",
        "failed": false,
        "fusion_request_id": "Pj2zeWThLw",
        "json": {
            "fusion.spark.worker.memory": "4g",
            "fusion.spark.worker.port": 8769,
            "fusion.spark.worker.webui.port": 8082,
            "spark.worker.cleanup.appDataTtl": 7200,
            "spark.worker.cleanup.enabled": true,
            "spark.worker.timeout": 30,
            "spark.worker.ui.retainedDrivers": 50
        },
        "msg": "OK (279 bytes)",
        "redirected": false,
        "server": "Jetty(9.4.12.v20180830)",
        "status": 200,
        "url": "http://localhost:8765/api/v1/configurations?prefix=spark.worker"
    }
}

我无法使用 {{spark_worker_cfg.json.fusion.spark.worker.memory}} 访问该值,我的问题似乎是由包含点的名称引起的:

The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'fusion'

我查看了两个 SO 帖子 ( and 2),它们看起来像我的问题的副本,但无法从中得出如何解决我当前问题的方法。

数据结构的 'json' 元素中的键包含文字点,而不是表示结构。这会导致问题,因为如果使用点分符号,Ansible 将不知道将它们视为文字。因此,使用方括号表示法来引用它们,而不是点:

- debug:
    msg: "{{ spark_worker_cfg['json']['fusion.spark.worker.memory'] }}"

(乍一看,这看起来像是一个需要解码的 JSON 编码字符串的问题,本来可以处理的:"{{ spark_worker_cfg.json | from_json }}"

您可以使用 json_query 过滤器来获取结果。 https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

msg="{{ spark_worker_cfg.json | json_query('fusion.spark.worker.memory') }}

编辑: 作为对您的评论的回应,我们返回空字符串这一事实使我相信查询不正确。在使用 json_query 过滤器时找到确切的查询可能会令人沮丧,所以我通常会事先使用 jsonpath 工具。我在下面的评论中链接了一个,但我个人使用 intelliJ 中的 jsonUtils 插件来找到我的路径(仍然需要调整,因为两者之间的路径处理方式略有不同)。

如果您的 json 看起来像这样:

{
  value: "theValue"
}

然后

json_query('value')

会起作用。

您传递给 json_query 的路径对于您要执行的操作不正确。

如果您的顶级对象被命名为 fusion_spark_worker_memory(没有句点),那么您的查询应该有效。我相信这些点正在把东西扔掉。可能有一种方法可以避开查询中的那些...

编辑 2:clockworknet 获胜!他两次都打败了我。 :鞠躬: