將 JSON 文件作為 Post Request Flask 發送 (Sending JSON File as Post Request Flask)


問題描述

將 JSON 文件作為 Post Request Flask 發送 (Sending JSON File as Post Request Flask)

我正在編寫一個測試來從社區中檢索前 n 個帖子。

在獲取這些值之前,我想從 JSON 文件中發布數據,而不是將它們分別發佈到端點。

我嘗試了 test_retrieve_recent_posts_existing_community 的細微變化,但不斷收到 TypeError

誰能建議我如何修復測試用例?

Route:

@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} 

Test:

def test_retrieve_recent_posts_existing_community(client):
    with open('posts.json') as posts_data:
        posts_json = json.dumps(posts_data)

    client.post('/api/v2/post/create', data=json.dump(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

Error:

TypeError:TextIOWrapper 類型的對像不是 JSON 可序列化的

文件(posts.json):

[
    {
        "postid": 2,
        "title": "Heading 2",
        "text": "Content of post 2",
        "published": "YYYY/MM/DD hh:mm:ss",
        "community": "tech"
    },
    {
        "postid": 3,
        "title": "Heading 3",
        "text": "Content of post 3",
        "published": "YYYY/MM/DD hh:mm:ss",
        "community": "tech"
    },
    {
        "postid": 4,
        "title": "Heading 4",
        "text": "Content of post 4",
        "published": "YYYY/MM/DD hh:mm:ss",
        "community": "art"
    },
    {
        "postid": 5,
        "title": "Heading 5",
        "text": "Content of post 5",
        "published": "YYYY/MM/DD hh:mm:ss",
        "community": "art"
    },
    {
        "postid": 6,
        "title": "Heading 6",
        "text": "Content of post 6",
        "published": "YYYY/MM/DD hh:mm:ss",
        "community": "science"
    },
    {
        "postid": 7,
        "title": "Heading 7",
        "text": "Content of post 7",
        "published": "YYYY/MM/DD hh:mm:ss",
        "community": "tech"
    }
]

文件鏈接 路由測試


參考解法

方法 1:

All errors in your test are caused by wrong usage of json module methods.

Here is a modified version of your test with comments on the changes

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

Notice that you also have a problem in the create method. It expects one object to be passed in the json body. and you're sending an array. So either change your json file to contain one object or change the create implementation to deal with an array of objects. for example change it to the following

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}

At this point the test should run, but it would result in AssertionError. That is because you have two problem in the implementation of recent_community_posts() method.

  1. You're extracting query parameters in the first two lines and you pass the "community" and the "top" as path parameters. so if community will always return false unless you pass it as a parameter in the url (/api/v2/post/retrieve/tech/2?community=tech&top=2) which is redundant.

  2. You're using jsonify inside the dictionary in the return statement like this:

    return {'data': jsonify(filtered_posts[:top]), 'message': "Filtered data based on community", 'status': 203}

jsonify returns a flask.wrappers.Response object which is not JSON serializable. you can replace it with the following

return jsonify({
    'data': filtered_posts[:top],
    'message': "Filtered data based on community",
    'status': 203
})

方法 2:

To upload the body of the request:

with open('posts.json') as posts_data:
    posts_json = json.load(posts_data)

Which output should be a list:

print(type(posts_json))
list

As to post the body should by dumped:

data=json.dumps(posts_json)

Which is a string:

Out[9]: '[{"postid": 2, "title": "Heading 2", "text": "Content of post 2", "published": "YYYY/MM/DD hh:mm:ss", "community": "tech"}, {"postid": 3, "title": "Heading 3", "text": "Content of post 3", "published": "YYYY/MM/DD hh:mm:ss", "community": "tech"}, {"postid": 4, "title": "Heading 4", "text": "Content of post 4", "published": "YYYY/MM/DD hh:mm:ss", "community": "art"}, {"postid": 5, "title": "Heading 5", "text": "Content of post 5", "published": "YYYY/MM/DD hh:mm:ss", "community": "art"}, {"postid": 6, "title": "Heading 6", "text": "Content of post 6", "published": "YYYY/MM/DD hh:mm:ss", "community": "science"}, {"postid": 7, "title": "Heading 7", "text": "Content of post 7", "published": "YYYY/MM/DD hh:mm:ss", "community": "tech"}]'

I think you have posts_json dumped twice. Could you try with only once?. Please.

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

方法 3:

In your test_retrieve_recent_posts_existing_community function, you're doing

posts_json = json.dumps(posts_data)

Now json.dumps takes a python object (dicts and lists) and turns it into a string, which is the textual representation in JSON. But that is already what you have in your file. Just do this instead:

with open('posts.json') as posts_data:
    posts_json = posts_data.read()

and again, in the client.post call, just do

data=posts_json

no need for json.dump.

(by SaurabhMostafa KashwaaRafael Valerojoao)

參考文件

  1. Sending JSON File as Post Request Flask (CC BY‑SA 2.5/3.0/4.0)

#Python #Testing #JSON #Flask






相關問題

如何從控制台中導入的文件中訪問變量的內容? (How do I access the contents of a variable from a file imported in a console?)

在 python 3.5 的輸入列表中添加美元符號、逗號和大括號 (Adding dollar signs, commas and curly brackets to input list in python 3.5)

為 KeyError 打印出奇怪的錯誤消息 (Strange error message printed out for KeyError)

django 1.9 中的 from django.views.generic.simple import direct_to_template 相當於什麼 (What is the equivalent of from django.views.generic.simple import direct_to_template in django 1.9)

查詢嵌入列表中的數組 (Querying for array in embedded list)

如何在 Python 中搜索子字符串是否在二進製文件中? (How to search if a substring is into a binary file in Python?)

為什麼要避免 while 循環? (Why avoid while loops?)

使用python的json模塊解析json請求 (Parse a json request using json module of python)

為什麼使用 py2app 模塊創建 mac 文件時出現錯誤? (Why i am getting Error when creating mac file using py2app module?)

當 python 線程在網絡調用(HTTPS)中並且發生上下文切換時會發生什麼? (What happens when the python thread is in network call(HTTPS) and the context switch happens?)

如何繪製一條帶斜率和一個點的線?Python (How to plot a line with slope and one point given? Python)

Pickle 找不到我不使用的模塊? (Pickle can't find module that I am not using?)







留言討論