如何使用Jinja2模板引擎生成json

时间:2021-11-14 20:45:53

I am trying to generate a json file from a .xlsx file.

我试图从.xlsx文件生成一个json文件。

so far I was able to get data from the file but I am not sure how to put them on json using jinja2. There is a problem in template structure. How can I solve this?

到目前为止,我能够从文件中获取数据,但我不知道如何使用jinja2将它们放在json上。模板结构存在问题。我怎么解决这个问题?

Output should be like this

输出应该是这样的

  "Matches": {    
    "1": {
      "time": "19:00",
      "teams": "Team 1 - Team 2"
    },
    "2": {
      "time": "21:00",
      "teams": "Team 3 - Team 4"
    },
    ...
    ...
    ...
  }

My code is something like this. Obviously template section is wrong.

我的代码是这样的。显然模板部分是错误的。

from openpyxl import load_workbook
from jinja2 import Template


start_coloumn_of_matches = 3
end_coloumn_of_matches = 20

wb = load_workbook(filename = 'myfile.xlsx')
sheet_ranges = wb['Sheet1']

keys = []
teams = []
times = []


for x in range(start_coloumn_of_matches, end_coloumn_of_matches + 1):
    team_column = 'A' + str(x)
    time_column = 'D' + str(x)
    teams.append(sheet_ranges[team_column].value)
    times.append(sheet_ranges[time_column].value)
    keys.append(x)



template = Template(''' 
"Matches": {
        {% for key in keys %}
      "{{key}}": 
        {% endfor %}
      {
        {% for team in teams %}
        "teams": "{{team}}",
        {% endfor %}
        {% for time in times %}
        "time": "{{time}}"
        {% endfor %}
        }

    }, 

    ''' )

print(template.render(teams = teams, times = times, keys = keys))

2 个解决方案

#1


0  

Manually constructing json runs the risk of accidentally producing an invalid json string. It's safer to construct the json using the json package in Python's standard library, and then render the json in your template. Constructing the json separately also simplfies the template.

手动构造json会冒着意外产生无效json字符串的风险。使用Python标准库中的json包构造json更安全,然后在模板中渲染json。分别构造json也简化了模板。

>>> import json
>>> import pprint

>>> # Construct some test data
>>> matches = ['1', '2', '3']
>>> times = ['19:00', '21:00', '23:00']
>>> teams = ['Team 1 - Team 2', 'Team 3 - Team 4', 'Team 5 - Team 6']

>>> # Combine the data structures to match the required output
>>> match_data = [dict(zip(['time', 'team'], pair)) for pair in zip(times, teams)]
>>> combined = {x: y for x, y in zip(matches, match_data)}
>>> pprint.pprint(combined)
{'1': {'team': 'Team 1 - Team 2', 'time': '19:00'},
 '2': {'team': 'Team 3 - Team 4', 'time': '21:00'},
 '3': {'team': 'Team 5 - Team 6', 'time': '23:00'}}

>>> # Serialise our object as json; setting the indent argument gives
>>> # the pretty printed format that we want.
>>> jdata = json.dumps(combined,  indent=2) 
>>> print(jdata)
{
  "1": {
    "time": "19:00",
    "team": "Team 1 - Team 2"
  },
  "2": {
    "time": "21:00",
    "team": "Team 3 - Team 4"
  },
  "3": {
    "time": "23:00",
    "team": "Team 5 - Team 6"
  }
}

>>> # Pass the json to the template for rendering.
>>> template = jinja2.Template("""{{ matches }}""")
>>> print(template.render(matches=jdata))
{
  "1": {
    "time": "19:00",
    "team": "Team 1 - Team 2"
  },
  "2": {
    "time": "21:00",
    "team": "Team 3 - Team 4"
  },
  "3": {
    "time": "23:00",
    "team": "Team 5 - Team 6"
  }
}

#2


0  

I find the answer. Zip the lists into 'matches' variable and construct the template like this:

我找到了答案。将列表压缩为'matches'变量并构造如下模板:

template = Template(''' 
"Matches": {
        {% for key, team, time in matches %}
      "{{key}}": 
      {
        "teams": "{{team}}",
        "time": "{{time}}"
        },
            {% endfor %}
    }
    ''' )


print(template.render(matches=zip(keys, teams, times)))

#1


0  

Manually constructing json runs the risk of accidentally producing an invalid json string. It's safer to construct the json using the json package in Python's standard library, and then render the json in your template. Constructing the json separately also simplfies the template.

手动构造json会冒着意外产生无效json字符串的风险。使用Python标准库中的json包构造json更安全,然后在模板中渲染json。分别构造json也简化了模板。

>>> import json
>>> import pprint

>>> # Construct some test data
>>> matches = ['1', '2', '3']
>>> times = ['19:00', '21:00', '23:00']
>>> teams = ['Team 1 - Team 2', 'Team 3 - Team 4', 'Team 5 - Team 6']

>>> # Combine the data structures to match the required output
>>> match_data = [dict(zip(['time', 'team'], pair)) for pair in zip(times, teams)]
>>> combined = {x: y for x, y in zip(matches, match_data)}
>>> pprint.pprint(combined)
{'1': {'team': 'Team 1 - Team 2', 'time': '19:00'},
 '2': {'team': 'Team 3 - Team 4', 'time': '21:00'},
 '3': {'team': 'Team 5 - Team 6', 'time': '23:00'}}

>>> # Serialise our object as json; setting the indent argument gives
>>> # the pretty printed format that we want.
>>> jdata = json.dumps(combined,  indent=2) 
>>> print(jdata)
{
  "1": {
    "time": "19:00",
    "team": "Team 1 - Team 2"
  },
  "2": {
    "time": "21:00",
    "team": "Team 3 - Team 4"
  },
  "3": {
    "time": "23:00",
    "team": "Team 5 - Team 6"
  }
}

>>> # Pass the json to the template for rendering.
>>> template = jinja2.Template("""{{ matches }}""")
>>> print(template.render(matches=jdata))
{
  "1": {
    "time": "19:00",
    "team": "Team 1 - Team 2"
  },
  "2": {
    "time": "21:00",
    "team": "Team 3 - Team 4"
  },
  "3": {
    "time": "23:00",
    "team": "Team 5 - Team 6"
  }
}

#2


0  

I find the answer. Zip the lists into 'matches' variable and construct the template like this:

我找到了答案。将列表压缩为'matches'变量并构造如下模板:

template = Template(''' 
"Matches": {
        {% for key, team, time in matches %}
      "{{key}}": 
      {
        "teams": "{{team}}",
        "time": "{{time}}"
        },
            {% endfor %}
    }
    ''' )


print(template.render(matches=zip(keys, teams, times)))