如何在Jinja2中查询复杂的JSON?

0s7z1bwu  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(155)

我正在Ansible中用Jinja2模板解析一个复杂的JSON,这个JSON有很多元素和随机数组。
例如,如果date < 2001适用于所有电机,我如何查询name & id的值?(这应该返回:Premium diesel&4).请注意,这是一个示例结构,在我的真实的场景中,它可以有随机的和更多的子节点.我需要的是一个查询来搜索整个树中的上述键.

{
   "cars":[
      {
         "Ford":[
            {
               "vehicle":{
                  "motor":[
                     {
                        "diesel":[
                           {
                              "regular":{
                                 "name":"Regular diesel",
                                 "specs":{
                                    "law":[
                                       {
                                          "id":1,
                                          "date":"2008"
                                       }
                                    ],
                                    "gas_station":[
                                       {
                                          "id":2,
                                          "date":"2002"
                                       }
                                    ]
                                 }
                              },
                              "premium":{
                                 "name":"Premium diesel",
                                 "specs":{
                                    "law":[
                                       {
                                          "id":3,
                                          "date":"2005"
                                       }
                                    ],
                                    "gas_station":[
                                       {
                                          "id":4,
                                          "date":"2000"
                                       }
                                    ]
                                 }
                              }
                           }
                        ]
                     }
                  ]
               }
            }
         ]
      }
   ]
}
oxiaedzo

oxiaedzo1#

Q:***"如果日期〈2001,如何查询name & id的值?***
(this应返回:优质柴油和4)
答:创建日期小于"2001"的项目列表

year: 2001
  vehicle_motors_year:
    2001:
    - brand: Ford
      id: 4
      name: Premium diesel
      type: gas_station
    - brand: Ford
      id: 6
      name: Natural gasoline
      type: gas_station
    - brand: VW
      id: 12
      name: Hybrid hydrogen
      type: gas_station

然后选择项目并设置其格式

result: "{{ vehicle_motors_year[year]|
              json_query('[].[name, id]')|
              map('join', ' & ') }}"

给出了预期结果

result:
  - Premium diesel & 4
  - Natural gasoline & 6
  - Hybrid hydrogen & 12

详情:
根据测试车辆的清单

cars:
      - Ford:
        - vehicle:
            motor:
            - diesel:
              - premium:
                  name: Premium diesel
                  specs:
                    gas_station:
                    - date: '2000'
                      id: 4
                    law:
                    - date: '2005'
                      id: 3
                regular:
                  name: Regular diesel
                  specs:
                    gas_station:
                    - date: '2002'
                      id: 2
                    law:
                    - date: '2008'
                      id: 1
            - gasoline:
              - natural:
                  name: Natural gasoline
                  specs:
                    gas_station:
                    - date: '2000'
                      id: 6
                    law:
                    - date: '2005'
                      id: 5
      - VW:
        - vehicle:
            motor:
            - hybrid:
              - hydrogen:
                  name: Hybrid hydrogen
                  specs:
                    gas_station:
                    - date: '2000'
                      id: 12
                    law:
                    - date: '2005'
                      id: 11

获取品牌和电机列表

brands: "{{ cars|map('first') }}"
  motors: "{{ cars|json_query(query_motors) }}"
  query_motors: '[].*[][].vehicle[].motor'

Give

brands:
  - Ford
  - VW
motors:
  - - diesel:
      - premium:
          name: Premium diesel
          specs:
            gas_station:
            - date: '2000'
              id: 4
            law:
            - date: '2005'
              id: 3
        regular:
          name: Regular diesel
          specs:
            gas_station:
            - date: '2002'
              id: 2
            law:
            - date: '2008'
              id: 1
    - gasoline:
      - natural:
          name: Natural gasoline
          specs:
            gas_station:
            - date: '2000'
              id: 6
            law:
            - date: '2005'
              id: 5
  - - hybrid:
      - hydrogen:
          name: Hybrid hydrogen
          specs:
            gas_station:
            - date: '2000'
              id: 12
            law:
            - date: '2005'
              id: 11

创建一个字典的品牌'车辆'发动机

vehicle_motors_str: |                                                                     
      {% for motor in motors %}                                                               
      {{ brands[loop.index0] }}:                                                              
      {% for fuels in motor %}                                                                
      {% for fuel,types in fuels.items() %}                                                   
      {% for type in types %}                                                                 
      {% for k,v in type.items() %}                                                           
        {{ fuel }}_{{ k }}:                                                                   
          {{ v }}                                                                             
      {% endfor %}                                                                            
      {% endfor %}                                                                            
      {% endfor %}                                                                            
      {% endfor %}                                                                            
      {% endfor %}                                                                            
    vehicle_motors: "{{ vehicle_motors_str|from_yaml }}"

给予

vehicle_motors:
    Ford:
      diesel_premium:
        name: Premium diesel
        specs:
          gas_station:
          - date: '2000'
            id: 4
          law:
          - date: '2005'
            id: 3
      diesel_regular:
        name: Regular diesel
        specs:
          gas_station:
          - date: '2002'
            id: 2
          law:
          - date: '2008'
            id: 1
      gasoline_natural:
        name: Natural gasoline
        specs:
          gas_station:
          - date: '2000'
            id: 6
          law:
          - date: '2005'
            id: 5
    VW:
      hybrid_hydrogen:
        name: Hybrid hydrogen
        specs:
          gas_station:
          - date: '2000'
            id: 12
          law:
          - date: '2005'
            id: 11

使用此字典查找 * date * 小于"2001"的项目

year: 2001
    vehicle_motors_year_str: |
      {{ year }}:
      {% for brand,fuels in vehicle_motors.items() %}
      {% for fuel,types in fuels.items() %}
      {% for k,v in types.specs.items() %}
      {% for i in v %}
      {% if i.date|int < year|int %}
      - name: {{ types.name }}
        id: {{ i.id }}
        brand: {{ brand }}
        type: {{ k }}
      {% endif %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
    vehicle_motors_year: "{{ vehicle_motors_year_str|from_yaml }}"

给予

vehicle_motors_year:
    2001:
    - brand: Ford
      id: 4
      name: Premium diesel
      type: gas_station
    - brand: Ford
      id: 6
      name: Natural gasoline
      type: gas_station
    - brand: VW
      id: 12
      name: Hybrid hydrogen
      type: gas_station

完整的测试行动手册示例

- hosts: localhost

  vars:

    cars:
      - Ford:
        - vehicle:
            motor:
            - diesel:
              - premium:
                  name: Premium diesel
                  specs:
                    gas_station:
                    - date: '2000'
                      id: 4
                    law:
                    - date: '2005'
                      id: 3
                regular:
                  name: Regular diesel
                  specs:
                    gas_station:
                    - date: '2002'
                      id: 2
                    law:
                    - date: '2008'
                      id: 1
            - gasoline:
              - natural:
                  name: Natural gasoline
                  specs:
                    gas_station:
                    - date: '2000'
                      id: 6
                    law:
                    - date: '2005'
                      id: 5
      - VW:
        - vehicle:
            motor:
            - hybrid:
              - hydrogen:
                  name: Hybrid hydrogen
                  specs:
                    gas_station:
                    - date: '2000'
                      id: 12
                    law:
                    - date: '2005'
                      id: 11
    
    brands: "{{ cars|map('first') }}"
    motors: "{{ cars|json_query(query_motors) }}"
    query_motors: '[].*[][].vehicle[].motor'

    vehicle_motors_str: |
      {% for motor in motors %}
      {{ brands[loop.index0] }}:
      {% for fuels in motor %}
      {% for fuel,types in fuels.items() %}
      {% for type in types %}
      {% for k,v in type.items() %}
        {{ fuel }}_{{ k }}:
          {{ v }}
      {% endfor %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
    vehicle_motors: "{{ vehicle_motors_str|from_yaml }}"

    year: 2001
    vehicle_motors_year_str: |
      {{ year }}:
      {% for brand,fuels in vehicle_motors.items() %}
      {% for fuel,types in fuels.items() %}
      {% for k,v in types.specs.items() %}
      {% for i in v %}
      {% if i.date|int < year|int %}
      - name: {{ types.name }}
        id: {{ i.id }}
        brand: {{ brand }}
        type: {{ k }}
      {% endif %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
    vehicle_motors_year: "{{ vehicle_motors_year_str|from_yaml }}"

  tasks:

    - debug:
        var: brands
    - debug:
        var: motors
    - debug:
        var: vehicle_motors
    - debug:
        var: vehicle_motors_year

如果去掉多余的列表

cars:
      Ford:
        vehicle:
          motor:
            diesel:
              premium:
                name: Premium diesel
                specs:
                  gas_station:
                    - {date: 2000, id: 4}
                  law:
                    - {date: 2005, id: 3}
              regular:
                name: Regular diesel
                specs:
                  gas_station:
                    - {date: 2002, id: 2}
                  law:
                    - {date: 2008, id: 1}
            gasoline:
              natural:
                name: Natural gasoline
                specs:
                  gas_station:
                    - {date: 2000, id: 6}
                  law:
                    - {date: 2005, id: 5}
      VW:
        vehicle:
          motor:
            hybrid:
              hydrogen:
                name: Hybrid hydrogen
                specs:
                  gas_station:
                    - {date: 2000, id: 12}
                  law:
                    - {date: 2005, id: 11}

创建字典 * brands_motors *

brands_motors: "{{ dict(cars.keys()|list|
                            zip(cars|
                                json_query('*.*.*.*.*')|
                                flatten(levels=2)|
                                map('flatten'))) }}"

给予

brands_motors:
    Ford:
    - name: Premium diesel
      specs:
        gas_station:
        - date: 2000
          id: 4
        law:
        - date: 2005
          id: 3
    - name: Regular diesel
      specs:
        gas_station:
        - date: 2002
          id: 2
        law:
        - date: 2008
          id: 1
    - name: Natural gasoline
      specs:
        gas_station:
        - date: 2000
          id: 6
        law:
        - date: 2005
          id: 5
    VW:
    - name: Hybrid hydrogen
      specs:
        gas_station:
        - date: 2000
          id: 12
        law:
        - date: 2005
          id: 11

创建电动机列表

motors_str: |
      {% for brand,motors in brands_motors.items() %}
      {% for motor in motors %}
      {% for spec,types in motor.specs.items() %}
      {% for type in types %}
      - brand: {{ brand }}
        name: {{ motor.name }}
        spec: {{ spec }}
        date: {{ type.date }}
        id: {{ type.id }}
      {% endfor %}
      {% endfor %}
      {% endfor %}
      {% endfor %}
    motors: "{{ motors_str|from_yaml }}"

给予

motors:
    - {brand: Ford, date: 2000, id: 4, name: Premium diesel, spec: gas_station}
    - {brand: Ford, date: 2005, id: 3, name: Premium diesel, spec: law}
    - {brand: Ford, date: 2002, id: 2, name: Regular diesel, spec: gas_station}
    - {brand: Ford, date: 2008, id: 1, name: Regular diesel, spec: law}
    - {brand: Ford, date: 2000, id: 6, name: Natural gasoline, spec: gas_station}
    - {brand: Ford, date: 2005, id: 5, name: Natural gasoline, spec: law}
    - {brand: VW, date: 2000, id: 12, name: Hybrid hydrogen, spec: gas_station}
    - {brand: VW, date: 2005, id: 11, name: Hybrid hydrogen, spec: law}

选择是微不足道的

year: 2001
    result: "{{ motors|
                selectattr('date', 'lt', year)|
                json_query('[].[name, id]')|
                map('join', ' & ') }}"

给出了预期结果

result:
  - Premium diesel & 4
  - Natural gasoline & 6
  - Hybrid hydrogen & 12

相关问题