Python Flask JSON в неправильном порядке: отправьте и получите функции - PullRequest
0 голосов
/ 28 февраля 2020

Функции post и get для моего Flask сервера выглядят следующим образом:

from flask import Flask, request
import json
app = Flask(__name__)

tasks=[]

#Create a new task
@app.route('/v1/tasks', methods=['POST'])
def post():
    data=request.get_json()
    if "title" not in data:
        return bulkadd(data)
    title=data["title"]
    tasks.append(json.dumps({"id": len(tasks)+1, "title": title, "is_completed": "false"}))
    index=len(tasks)
    return json.dumps({"id": index}), 201

#List all tasks created
@app.route('/v1/tasks', methods=['GET'])
def getall():
   app.logger.info({"tasks": tasks})
   return json.dumps({"tasks": tasks})

После двойного вызова post это вывод команды get:

{"tasks": ["{\"is_completed\": \"false\", \"id\": 1, \"title\":\"Test Task 2\"}", "{\"is_completed\": \"false\", \"id\": 2, \"t:03] "POST /v1/tasks HTTP/1.1" 201 -itle\": \"Test Task 2\"}"]}

Вместо этого Вот как я хотел бы получить формат вывода:

{
   tasks: [
     {id: 1, title: "Test Task 1", is_completed: true},
     {id: 2, title: "Test Task 2", is_completed: false}
   ]
}

Почему порядок отличается и что означает \ "?

Спасибо за вашу помощь!

Редактировать 1: Не могли бы вы также помочь мне, почему следующий тест для публикации функции выдает эту ошибку?:

Разве это не генерирует действительный json?

return json.dumps({"id": index}), 201

_____________________________________ test_create_task _____________________________________
    def test_create_task():
        r = requests.post('http://localhost:5000/v1/tasks', json={"title": "My First Task"})>       assert isinstance(r.json()["id"], int)

project1-test3.py:6:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/alexanderfarr/.local/lib/python3.6/site-packages/requests/models.py:898: in json      
    return complexjson.loads(self.text, **kwargs)
/usr/lib/python3/dist-packages/simplejson/__init__.py:518: in loads
    return _default_decoder.decode(s)
/usr/lib/python3/dist-packages/simplejson/decoder.py:370: in decode
    obj, end = self.raw_decode(s)

1 Ответ

1 голос
/ 28 февраля 2020

Причина, по которой выходные данные в списке tasks имеют \", заключается в том, что отдельные элементы на самом деле являются строкой, а учитывая, что JSON использует символ " для кавычек строк, литерал " внутри него нужно экранировать, добавив перед ним символ экранирования, \, что делает \". Поскольку вам, очевидно, не нужна строка, а реальный объект, вам просто не нужно кодировать этот объект в строку перед добавлением его в список.

Поэтому вместо

def post():
    ...
    tasks.append(json.dumps({"id": len(tasks)+1, "title": title, "is_completed": "false"}))

Просто сделайте

    tasks.append({"id": len(tasks)+1, "title": title, "is_completed": "false"})

Теперь, если вам нужен определенный c порядок вывода для ключей определенным c (не алфавитным c) способом, этот поток SO входит в детали позади этого. Вкратце, вы можете сделать это для функции post:

import json
from collections import OrderedDict
from flask import Flask, request

app = Flask(__name__)
tasks = []

# Create a new task
@app.route('/v1/tasks', methods=['POST'])
def post():
    data = request.get_json()
    if "title" not in data:
        return bulkadd(data)
    title = data["title"]
    tasks.append(OrderedDict((
        ('id', len(tasks) + 1),
        ('title', title),
        ('is_completed', False),
    )))
    index = len(tasks)
    return json.dumps({"id": index}), 201


# List all tasks created
@app.route('/v1/tasks', methods=['GET'])
def getall():
   app.logger.info({"tasks": tasks})
   return json.dumps({"tasks": tasks}, indent=4)

Пример выполнения:

$ curl http://127.0.0.1:5000/v1/tasks --data '{"title": "hi"}' -H 'Content-Type: application/json'
{"id": 1}
$ curl http://127.0.0.1:5000/v1/tasks
{
    "tasks": [
        {
            "id": 1,
            "title": "hi",
            "is_completed": false
        }
    ]
}

Альтернатива, с использованием requests (с последним достаточно версии, которая поддерживает ключевой аргумент json):

>>> import requests
>>> r = requests.post('http://localhost:5000/v1/tasks', json={"title": "My First Task"})
>>> r.json()["id"]
1
>>> print(requests.get('http://localhost:5000/v1/tasks').text)
{
    "tasks": [
        {
            "id": 1,
            "title": "My First Task",
            "is_completed": false
        }
    ]
}

Возможно, вы захотите не заключать в кавычки false для is_completed (что я и сделал здесь), поскольку это превращает значение в строку вместо логического значения, которое вы, возможно, намереваетесь передать. Также обратите внимание, что для GET версии этой конечной точки я добавил аргумент indent=4 для json.dumps, чтобы было выполнено удобное форматирование, но учтите, что это увеличивает размер полезной нагрузки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...