Search code examples
ansiblejmespath

JMESPath - how to prune a tree


I have a JSON data structure (actually, YAML) and want to reformat the stucture, but can't figure out how to get this to work correctly. This will be used within a jinja2 template in Ansible. The tool I have tried to use is the json_query filter, which uses JMESPath.

Input:

"users": {
  "Administrators": [
    "user1",
    "user2": {
       "ssh_keys": "...."
    },
    "user3"
  ],
  "Users": [
     "user4"
  ]
}

I would like to reform this JSON into this (stripping the ssh_key part in the process)

"Administrators": [
  "user1",
  "user2",
  "user3"
],
"Users": [
  "user4"
]

How can I do that in jinja2? I have found the json_query filter that seems like the right tool for the job, but haven't found a query that accomplishes what I am looking for.


Solution

  • Firstlly i would recommand reformatting the json if you can. A good format would make this extremely easy, for instance:

    "users": {
      "Administrators": [
        {"name": "user1, "ssh_keys": None},
        {"name": "user2, "ssh_keys": "...."},
        {"name": "user3, "ssh_keys": None},
      ],
      "Users": [
         "user4"
      ]
    }
    

    If your unable to do so, try this (this refers to the Administrators but applies for whatever):

     - set_fact:
          admins: "{{ (users | json_query(item) | default([])) | union(admins | default([])) }}"
       with_items:
          - "Administrators[?type(@) == 'object'][keys(@)][][]"
          - "Administrators[?type(@)=='string']"
    

    This would create a admins array with only usernames from your users json. Than you can set another fact that contains admins and users