Python 将JSON文件作为Post请求发送

Python 将JSON文件作为Post请求发送,python,json,flask,testing,Python,Json,Flask,Testing,我正在编写一个测试,以从社区中检索前n个帖子 在获取这些值之前,我希望从JSON文件发布数据,而不是将它们单独发布到端点 我尝试了test\u retrieve\u receive\u posts\u existing\u community的一些细微变化,但不断得到TypeError 有人能建议我如何修复测试用例吗 路线: @app.route('/api/v2/post/retrieve/<community>/<top>', methods=['GET']) def

我正在编写一个测试,以从社区中检索前n个帖子

在获取这些值之前,我希望从JSON文件发布数据,而不是将它们单独发布到端点

我尝试了
test\u retrieve\u receive\u posts\u existing\u community
的一些细微变化,但不断得到
TypeError

有人能建议我如何修复测试用例吗

路线:

@app.route('/api/v2/post/retrieve/<community>/<top>', methods=['GET'])
def recent_community_posts(community=None, top=0):
    community = request.args.get('community')
    top       = request.args.get('top')
    filtered_posts = []
    if community:
        for post in posts:
            if post['community'] == community:
                filtered_posts.append(post)
    
    if len(filtered_posts) == 0:
        return {'message': 'Community does not exist ...', 'status': 402}
    return {'data': jsonify(filtered_posts[:top]), 'message': "Filtered data based on community", 'status': 203} 

错误:

TypeError:TextIOWrapper类型的对象不可JSON序列化

文件(posts.json):


链接到文件和

以上载请求正文:

with open('posts.json') as posts_data:
    posts_json = json.load(posts_data)
哪个输出应该是一个列表:

print(type(posts_json))
list
至于邮寄,正文应通过以下方式发送:

data=json.dumps(posts_json)
这是一个字符串:

Out[9]:“[{“posted”:2,“title”:“Heading 2”,“text”:“post的内容” 2、“已出版”:“YYYY/MM/DD hh:MM:ss”,“社区”:“技术”}, {“postd”:3,“title”:“Heading 3”,“text”:“post 3的内容”, “已发布”:“YYYY/MM/DD hh:MM:ss”,“社区”:“tech”},{“postid”: 4,“标题”:“标题4”,“正文”:“第4篇文章的内容”,“已出版”: “YYYY/MM/DD hh:MM:ss”,“社区”:“艺术”},{“postid”:5,“标题”: “标题5”,“正文”:“第5篇文章的内容”,“出版”:“YYYY/MM/DD” hh:mm:ss,“社区”:“艺术”},{“postid”:6,“标题”:“标题6”, “正文”:“第6篇文章的内容”,“已发布”:“YYYY/MM/DD hh:MM:ss”, “社区”:“科学”},{“postid”:7,“标题”:“标题7”,“正文”: “第7篇文章的内容”,“已发布”:“YYYY/MM/DD hh:MM:ss”,“社区”: “技术”}]

我想你已经被甩了两次了。你能试一下吗?。求你了

def test_retrieve_recent_posts_existing_community(client):
    with open('posts.json') as posts_data:
        posts_json = json.load(posts_data)
    #SMALL CHANGE BELOW
    client.post('/api/v2/post/create', data=json.dumps(posts_json), content_type='application/json')
    response = client.get('/api/v2/post/retrieve/tech/2')
    data = json.load(response.get_data(as_text=True))
    assert "Filtered data" in data["message"] and data["status"] == 203

在您的测试(检索)(retrieve)(最近发布)(posts)(现有)(community)功能中

posts_json = json.dumps(posts_data)
现在json.dumps接受一个python对象(dicts和list)并将其转换为字符串,这是json中的文本表示形式。但这已经是你的档案了。只需这样做:

with open('posts.json') as posts_data:
    posts_json = posts_data.read()
同样,在client.post call中,只需执行以下操作

data=posts_json

不需要json.dump。

测试中的所有错误都是由错误使用json模块方法引起的

下面是您的测试的修改版本,其中包含对更改的注释

def test_retrieve_recent_posts_existing_community(client):
with open('posts.json') as posts_data:
    posts_json = json.load(posts_data)  # posts data is a TextIOWrapper object. you read it using load not dumps

    # posts_json is a list and should be turned into a json string using json.dumps not dump
    client.post('/api/v2/post/create', data=json.dumps(posts_json), content_type='application/json')

    response = client.get('/api/v2/post/retrieve/tech/2')
    data = json.loads(response.get_data(as_text=True))  # use loads not load to read the json string.
    assert "Filtered data" in data["message"] and data["status"] == 203
请注意,create方法中也有一个问题。它希望在json主体中传递一个对象。你正在发送一个数组。因此,要么将json文件更改为包含一个对象,要么将create实现更改为处理一个对象数组。例如,将其更改为以下内容

def create():
data_list = request.get_json()
for data in data_list:
    postid = data['postid']
    title = data['title']
    text = data['text']
    published = data['published']
    community = data['community']
    new_post = {
        'postid': postid,
        'title': title,
        'text': text,
        'published': published,
        'community': community
    }
    posts.append(new_post)
return {'message': "Post created successfully!", 'status': 202}
return jsonify({
    'data': filtered_posts[:top],
    'message': "Filtered data based on community",
    'status': 203
})
此时测试应该运行,但会导致AssertionError。这是因为在最近的_community_posts()方法的实现中有两个问题

  • 在前两行中提取查询参数,并将“community”和“top”作为路径参数传递。因此,
    if community
    将始终返回false,除非将其作为冗余url(/api/v2/post/retrieve/tech/2?community=tech&top=2)中的参数传递

  • 您在return语句中使用字典中的jsonify,如下所示:

    返回{'data':jsonify(filtered_posts[:top]),'message':“基于社区的过滤数据”,“status”:203}

  • jsonify返回一个flask.wrappers.Response对象,该对象不可JSON序列化。 您可以将其替换为以下内容

    def create():
    data_list = request.get_json()
    for data in data_list:
        postid = data['postid']
        title = data['title']
        text = data['text']
        published = data['published']
        community = data['community']
        new_post = {
            'postid': postid,
            'title': title,
            'text': text,
            'published': published,
            'community': community
        }
        posts.append(new_post)
    return {'message': "Post created successfully!", 'status': 202}
    
    return jsonify({
        'data': filtered_posts[:top],
        'message': "Filtered data based on community",
        'status': 203
    })
    

    谢谢Rafael,我尝试了您的测试用例,但得到了相同的错误。现在让我们试试:)这次不同的错误:
    json.decoder.jsondecoderror:期望值:第1行第1列(char 0)
    调用或服务器中的错误在哪里?。你有服务器的完整代码吗?它位于
    data=json.load(response.get\u data(as\u text=True))
    Its给出:
    AttributeError:'str'对象没有属性“read”