【问题标题】:How to return a json file line by line in flask?如何在烧瓶中逐行返回一个json文件?
【发布时间】:2020-08-24 20:29:37
【问题描述】:

我正在编写一个 api 来下载 json 文件。假设我有 3 个字典:

{"task_name":"task1","task_info":"aaaaa"}
{"task_name":"task2","task_info":"bbbbb"}
{"task_name":"task3","task_info":"ccccc"}

我想将这些 dict 返回到一个 json 文件中。这是我所做的:

data = json.dumps(tasks_info, default=str)
response = make_response(data, 200, {'mimetype': 'application/json'})
response.headers['Content-Disposition'] = "attachment;filename={}.json".format(urllib.parse.quote('result'))
return response

tasks_info 是一个包含 3 个字典的列表。 结果文件是这样打开的:

[{"task_name":"task1","task_info":"aaaaa"},{"task_name":"task2","task_info":"bbbbb"},{"task_name":"task3","task_info":"ccccc"}]

这是一条很长的线。 我想得到的看起来像

[   // the '[' and ']' is not necessary
{"task_name":"task1","task_info":"aaaaa"},
{"task_name":"task2","task_info":"bbbbb"},
{"task_name":"task3","task_info":"ccccc"}
]

我希望每个 dict 都显示在不同的行中,而不是每个 dict 都显示在同一行中。 有没有办法改变结果文件的样子?

【问题讨论】:

标签: python json flask


【解决方案1】:

格式化此输出的相关命令发生在 json.dumps() 中。你可以给出一堆命令来格式化你的 json。一种常规的方法是定义缩进级别:

import json

tasks_info = [{"task_name":"task1","task_info":"aaaaa"},{"task_name":"task2","task_info":"bbbbb"},{"task_name":"task3","task_info":"ccccc"}]
data = json.dumps(tasks_info, indent=2)
print(data)

将 json 漂亮地打印到:

[
  {
    "task_info": "aaaaa", 
    "task_name": "task1"
  }, 
  {
    "task_info": "bbbbb", 
    "task_name": "task2"
  }, 
  {
    "task_info": "ccccc", 
    "task_name": "task3"
  }
]

要获得所需的确切格式,您需要定义自己的格式化程序类。我使用了this answer 并对其进行了编辑以符合您的格式要求。完整代码如下:

import _ctypes
import json
import re

class OneDictPerLine(object):
    def __init__(self, value):
        self.value = value
    def __repr__(self):
        if not isinstance(self.value, list):
            return repr(self.value)
        else:  # Sort the representation of any dicts in the list.
            reps = ('{{{}}}'.format(', '.join(
                        ('{!r}: {!r}'.format(k, v) for k, v in sorted(v.items()))
                    )) if isinstance(v, dict)
                        else
                    repr(v) for v in self.value)
            return '[ \n' + ',\n'.join(reps) + '\n ]'


def di(obj_id):
    """ Reverse of id() function. """
    # from https://stackoverflow.com/a/15012814/355230
    return _ctypes.PyObj_FromPtr(obj_id)


class MyEncoder(json.JSONEncoder):
    FORMAT_SPEC = "@@{}@@"
    regex = re.compile(FORMAT_SPEC.format(r"(\d+)"))

    def default(self, obj):
        return (self.FORMAT_SPEC.format(id(obj)) if isinstance(obj, OneDictPerLine)
                else super(MyEncoder, self).default(obj))

    def encode(self, obj):
        format_spec = self.FORMAT_SPEC  # Local var to expedite access.
        json_repr = super(MyEncoder, self).encode(obj)  # Default JSON repr.

        # Replace any marked-up object ids in the JSON repr with the value
        # returned from the repr() of the corresponding Python object.
        for match in self.regex.finditer(json_repr):
            id = int(match.group(1))
            # Replace marked-up id with actual Python object repr().
            json_repr = json_repr.replace(
                       '"{}"'.format(format_spec.format(id)), repr(di(id)))

        return json_repr


tasks_info = [{"task_name":"task1","task_info":"aaaaa"},{"task_name":"task2","task_info":"bbbbb"},{"task_name":"task3","task_info":"ccccc"}]
data = json.dumps(OneDictPerLine(tasks_info), cls=MyEncoder)
print(data)
#make response and return data ...

输出:

[ 
{'task_info': 'aaaaa', 'task_name': 'task1'},
{'task_info': 'bbbbb', 'task_name': 'task2'},
{'task_info': 'ccccc', 'task_name': 'task3'}
]

【讨论】:

  • 这很酷。如果我的输出看起来像 ``` {'task_info': 'aaaaa', 'task_name': 'task1'}, {'task_info': 'bbbbb', 'task_name': 'task2'}, {' task_info': 'ccccc', 'task_name': 'task3'} ``` 我的意思是删除数组,每一行都是一个字典
  • @McCreeFeng 当然可以。将OneDictPerLine()的return语句替换为return ',\n'.join(reps)
猜你喜欢
  • 2021-12-22
  • 2019-06-24
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-24
  • 2018-09-10
相关资源
最近更新 更多