Json_query and hyphens issue

Hello

I’ve trying to get it working for hours now and no luck.

I’m querying Proxmox LXC network info from the API and the structure is:

json
  data
    ip-addresses
      lo: ip-address
      eth0: ip-address

The task looks like this:

- name: Get LXC IP address
  ansible.builtin.debug:
    var: item
  loop: '{{ lxclist.json | community.general.json_query("data[?name==`eth0`].ip-addresses") }}'
  tags: apitest

NOTE: If I remove the .ip-addresses part, it works, I get the whole eth0 network info, but I want to get the IP address.

This generates this kind of error: JMESPathError in json_query filter plugin:\nBad jmespath expression: Unknown token '-'.

There’s an issue here where someone has the same issue and they’re saying that’s how it should work and you should use quotes to make it work, but it won’t.

Here are the combinations I have tried:

'{{ lxclist.json | community.general.json_query("data[?name==`eth0`].\"ip-addresses\"") }}'

Error: template error while templating string: expected token ',', got 'ip'. String: {{ lxclist.json | community.general.json_query(\"data[?name==`eth0`].\\\\\"ip-addresses\\\\\"\"

'{{ lxclist.json | community.general.json_query("data[?name==`eth0`].""ip-addresses""") }}'

Error: JMESPathError in json_query filter plugin:\nBad jmespath expression: Unknown token '-'

"{{ lxclist.json | community.general.json_query('data[?name==`eth0`].ip-addresses') }}"

Error: JMESPathError in json_query filter plugin:\nBad jmespath expression: Unknown token '-'

"{{ lxclist.json | community.general.json_query('data[?name==`eth0`].`ip-addresses`') }}"

Error: JMESPathError in json_query filter plugin:\nExpecting: ['quoted_identifier', 'unquoted_identifier', 'lbracket', 'lbrace'], got: literal: Parse error at column 20, token \"ip-addresses\" (LITERAL)

omg… half a day of trial and error and this turned out to be the winning solution:
To make it easier, I created a separate task that disables IPv6 on the remote host.

- name: Get LXC IP address.
  ansible.builtin.debug:
    msg: "{{ lxclist.json | community.general.json_query(query) }}"
  register: ipaddress
  tags: apitest
  vars:
    query: 'data[?name != `lo`]."ip-addresses"[*]."ip-address"'

This can be simplified

- debug:
    var: result
  vars:
    _query: '*.eth0'
    result: "{{ lxclist.json.data | json_query(_query) }}"

Note: query is a reserved name.

That doesn’t return anything, unfortunately. Doesn’t error, the value is null.

The whole JSON block from the previous task with a register named lxclist.

I’m trying to get the ip-address of the network interface where the name isn’t lo.

"lxclist": {
	"cache_control": "max-age=0",
	"changed": false,
	"connection": "close",
	"content_length": "384",
	"content_type": "application/json;charset=UTF-8",
	"cookies": {},
	"cookies_string": "",
	"date": "Sun, 06 Jul 2025 10:49:24 GMT",
	"elapsed": 0,
	"expires": "Sun, 06 Jul 2025 10:49:24 GMT",
	"failed": false,
	"json": {
		"data": [
			{
				"hardware-address": "00:00:00:00:00:00",
				"hwaddr": "00:00:00:00:00:00",
				"inet": "127.0.0.1/8",
				"ip-addresses": [
					{
						"ip-address": "127.0.0.1",
						"ip-address-type": "inet",
						"prefix": "8"
					}
				],
				"name": "lo"
			},
			{
				"hardware-address": "00:24:00:07:a9:00",
				"hwaddr": "00:24:00:07:a9:00",
				"inet": "192.168.2.11/26",
				"ip-addresses": [
					{
						"ip-address": "192.168.2.11",
						"ip-address-type": "inet",
						"prefix": "26"
					}
				],
				"name": "eth0"
			}
		]
	},
	"msg": "OK (384 bytes)",
	"pragma": "no-cache",
	"redirected": false,
	"server": "pve-api-daemon/3.0",
	"status": 200,
	"url": "https://pmxhost.domain.local:8006/api2/json/nodes/pmxhost/lxc/106/interfaces"
}

Then, you don’t need the filter json_query. For example,

- # get the ip-address of the network interface where the name isn’t lo
  debug:
    var: result
  vars:
    result: "{{ lxclist.json.data | rejectattr('name', 'eq', 'lo')
                                  | map(attribute='ip-addresses')
                                  | flatten
                                  | map(attribute='ip-address') }}"

gives

  result:
    - 192.168.2.11

As a side note, you might want to create a dictionary first

- debug:
    var: ip_addresses
  vars:
    _query: '[].[name, "ip-addresses"[]."ip-address"]'
    ip_addresses: "{{ dict(lxclist.json.data | json_query(_query)) }}"

gives

  ip_addresses:
      eth0:
        - 192.168.2.11
      lo:
        - 127.0.0.1

Then, the searching is much easier.