如何在 Ansible 中获取具有动态变化位置的 Json 数组元素
How to grab Json array element having dynamically changing position in Ansible
下面是我的 json 文件,其中 log
数组位于 server
数组中,而 domain
数组位于 domain
数组中。
[
{
"?xml": {
"attributes": {
"encoding": "UTF-8",
"version": "1.0"
}
}
},
{
"domain": [
{
"name": "mydom"
},
{
"domain-version": "12.2.1.3.0"
},
{
"server": [
{
"name": "AdminServer"
},
{
"ssl": {
"name": "AdminServer"
}
},
{
"listen-port": "12400"
},
{
"listen-address": "mydom.host1.bank.com"
}
]
},
{
"server": [
{
"name": "myserv1"
},
{
"ssl": [
{
"name": "myserv1"
},
{
"login-timeout-millis": "25000"
}
]
},
{
"log": [
{
"name": "myserv1"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
]
}
]
},
{
"server": [
{
"name": "myserv2"
},
{
"ssl": {
"name": "myserv2"
}
},
{
"reverse-dns-allowed": "false"
},
{
"log": [
{
"name": "myserv2"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
]
}
]
}
]
}
]
log
数组在server
数组中的位置可能会发生变化,如上面的json所示。
我希望获取如下输出:
myserv1_log: "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
myserv2_log: "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
我面临两个挑战。
server
可能并不总是 domain
数组的第 3 个键。
log
数组可能并不总是所有服务器数组的键,因此不应打印。例如。服务器名称 AdminServer 没有任何日志列表,而 myserv1 和 myserv2 有。
此外,log
如果存在,可能并不总是 server
数组的第二个键,如 json.
中所示
当 log 始终是 server
数组的第二个元素时的解决方案如下:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file.json') | from_json }}"
tasks:
- name: display
debug:
msg: "name: {{ servername }} --> filename: {{ filename }}"
loop: "{{ json[1].domain }}"
vars:
servername: "{{ item.server.0.name }}_log"
filename: "{{ item['server'][2]['log'][1]['file-name'] }}"
when: item.server is defined and item.server.2.log is defined
请多多指教。
你有很多解决方案,一个:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file.json') | from_json }}"
tasks:
- name: display
debug:
msg: "{{ server.0.name }} -> {{ filename.0.log[1]['file-name'] }}"
loop: "{{ json[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
filename: "{{ item.server | selectattr('log', 'defined') }}"
when: item.server is defined and (item.server | selectattr('log', 'defined')) != []
结果:
skipping: [localhost] => (item={'name': 'mydom'})
skipping: [localhost] => (item={'domain-version': '12.2.1.3.0'})
skipping: [localhost] => (item={'server': [{'name': 'AdminServer'}, {'ssl': {'name': 'AdminServer'}}, {'listen-port': '12400'}, {'listen-address': 'mydom.host1.bank.com'}]})
ok: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': [{'name': 'myserv1'}, {'login-timeout-millis': '25000'}]}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]}) => {
"msg": "myserv1 -> /web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
ok: [localhost] => (item={'server': [{'name': 'myserv2'}, {'ssl': {'name': 'myserv2'}}, {'reverse-dns-allowed': 'false'}, {'log': [{'name': 'myserv2'}, {'file-name': '/web/bea_logs/domains/mydom/myserv2/myserv2.log'}]}]}) => {
"msg": "myserv2 -> /web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
尽管您遇到了问题,请尝试另一个解决方案:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file.json') | from_json }}"
tasks:
- name: display
set_fact:
values: "{{ values | d([]) + [v] }}"
loop: "{{ json[1].domain }}"
vars:
v: >-
{%- set dico = (item | dict2items).0.value -%}
{%- set result = {} -%}
{%- for i in dico -%}
{%- for x in i if x in ["name", "log"] -%}
{%- if result.update({x: i[x]}) -%}{% endif -%}
{%- endfor -%}
{%- endfor -%}
{%- if 'log' in result %}{{ result }}{% endif -%}
when: item.server is defined and v != ''
- debug:
msg: "{{ item.name }} -> {{ item.log[1]['file-name'] }}"
loop: "{{ values }}"
下面是我的 json 文件,其中 log
数组位于 server
数组中,而 domain
数组位于 domain
数组中。
[
{
"?xml": {
"attributes": {
"encoding": "UTF-8",
"version": "1.0"
}
}
},
{
"domain": [
{
"name": "mydom"
},
{
"domain-version": "12.2.1.3.0"
},
{
"server": [
{
"name": "AdminServer"
},
{
"ssl": {
"name": "AdminServer"
}
},
{
"listen-port": "12400"
},
{
"listen-address": "mydom.host1.bank.com"
}
]
},
{
"server": [
{
"name": "myserv1"
},
{
"ssl": [
{
"name": "myserv1"
},
{
"login-timeout-millis": "25000"
}
]
},
{
"log": [
{
"name": "myserv1"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
]
}
]
},
{
"server": [
{
"name": "myserv2"
},
{
"ssl": {
"name": "myserv2"
}
},
{
"reverse-dns-allowed": "false"
},
{
"log": [
{
"name": "myserv2"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
]
}
]
}
]
}
]
log
数组在server
数组中的位置可能会发生变化,如上面的json所示。
我希望获取如下输出:
myserv1_log: "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
myserv2_log: "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
我面临两个挑战。
server
可能并不总是domain
数组的第 3 个键。log
数组可能并不总是所有服务器数组的键,因此不应打印。例如。服务器名称 AdminServer 没有任何日志列表,而 myserv1 和 myserv2 有。
此外,log
如果存在,可能并不总是 server
数组的第二个键,如 json.
当 log 始终是 server
数组的第二个元素时的解决方案如下:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file.json') | from_json }}"
tasks:
- name: display
debug:
msg: "name: {{ servername }} --> filename: {{ filename }}"
loop: "{{ json[1].domain }}"
vars:
servername: "{{ item.server.0.name }}_log"
filename: "{{ item['server'][2]['log'][1]['file-name'] }}"
when: item.server is defined and item.server.2.log is defined
请多多指教。
你有很多解决方案,一个:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file.json') | from_json }}"
tasks:
- name: display
debug:
msg: "{{ server.0.name }} -> {{ filename.0.log[1]['file-name'] }}"
loop: "{{ json[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
filename: "{{ item.server | selectattr('log', 'defined') }}"
when: item.server is defined and (item.server | selectattr('log', 'defined')) != []
结果:
skipping: [localhost] => (item={'name': 'mydom'})
skipping: [localhost] => (item={'domain-version': '12.2.1.3.0'})
skipping: [localhost] => (item={'server': [{'name': 'AdminServer'}, {'ssl': {'name': 'AdminServer'}}, {'listen-port': '12400'}, {'listen-address': 'mydom.host1.bank.com'}]})
ok: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': [{'name': 'myserv1'}, {'login-timeout-millis': '25000'}]}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]}) => {
"msg": "myserv1 -> /web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
ok: [localhost] => (item={'server': [{'name': 'myserv2'}, {'ssl': {'name': 'myserv2'}}, {'reverse-dns-allowed': 'false'}, {'log': [{'name': 'myserv2'}, {'file-name': '/web/bea_logs/domains/mydom/myserv2/myserv2.log'}]}]}) => {
"msg": "myserv2 -> /web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
尽管您遇到了问题,请尝试另一个解决方案:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file.json') | from_json }}"
tasks:
- name: display
set_fact:
values: "{{ values | d([]) + [v] }}"
loop: "{{ json[1].domain }}"
vars:
v: >-
{%- set dico = (item | dict2items).0.value -%}
{%- set result = {} -%}
{%- for i in dico -%}
{%- for x in i if x in ["name", "log"] -%}
{%- if result.update({x: i[x]}) -%}{% endif -%}
{%- endfor -%}
{%- endfor -%}
{%- if 'log' in result %}{{ result }}{% endif -%}
when: item.server is defined and v != ''
- debug:
msg: "{{ item.name }} -> {{ item.log[1]['file-name'] }}"
loop: "{{ values }}"