简体   繁体   English

如何在 flask 中逐行返回 json 文件?

[英]How to return a json file line by line in flask?

I am writing a api to download json file.我正在写一个 api 来下载 json 文件。 Suppose I have 3 dict:假设我有 3 个字典:

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

I want to return these dict into one json file.Here is what I did:我想将这些字典返回到一个 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 is a list that contains 3 dict. tasks_info 是一个包含 3 个字典的列表。 The result file open like that:结果文件像这样打开:

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

It is a very long line.这是一条很长的线。 What I want to get looks like我想得到的看起来像

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

I want every dict show in a distinct line instead of every dict shown in same line.我希望每个 dict 都显示在不同的行中,而不是每个 dict 都显示在同一行中。 Are there any way to change the result file look like?有没有办法改变结果文件的样子?

The relevant command that formats this output takes place in json.dumps().格式化此 output 的相关命令发生在 json.dumps() 中。 There are a bunch of commands you can give to format your json.你可以给出一堆命令来格式化你的 json。 A conventional approach is to define the indent level:一种传统的方法是定义缩进级别:

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)

Which pretty-prints the json into:它将 json 漂亮地打印到:

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

To achieve the exact formatting you desire, you need to define your own formatter class.要获得所需的精确格式,您需要定义自己的格式化程序 class。 I used this answer and edited it to fit your formatting requirements.我使用了这个答案并对其进行了编辑以符合您的格式要求。 Here is the full code:这是完整的代码:

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 ...

output: output:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM