From 83fb89d9a9bd87eb2a61380896f7738bea4ac35c Mon Sep 17 00:00:00 2001 From: varun Date: Fri, 4 Sep 2026 03:07:29 +0530 Subject: [PATCH] Return the created row as a JSON object instead of a single-item list --- piccolo_api/crud/endpoints.py | 6 +++++- tests/crud/test_crud_endpoints.py | 19 +++++++++++++++++++ tests/fastapi/test_fastapi_endpoints.py | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/piccolo_api/crud/endpoints.py b/piccolo_api/crud/endpoints.py index 5174a1f7..2b8bc28c 100644 --- a/piccolo_api/crud/endpoints.py +++ b/piccolo_api/crud/endpoints.py @@ -982,7 +982,11 @@ async def post_single( request=request, ) response = await row.save().run() - json = dump_json(response) + # `save()` on a new row inserts it and returns a list with + # a single item (the primary key of the inserted row) - we + # only ever insert one row here, so unwrap it into a plain + # object instead of returning a single-item list. + json = dump_json(response[0]) # Returns the id of the inserted row. return CustomJSONResponse(json, status_code=201) except ValueError: diff --git a/tests/crud/test_crud_endpoints.py b/tests/crud/test_crud_endpoints.py index 669e5af4..141478dc 100644 --- a/tests/crud/test_crud_endpoints.py +++ b/tests/crud/test_crud_endpoints.py @@ -1357,6 +1357,25 @@ def test_success(self): self.assertEqual(movie.name, json["name"]) self.assertEqual(movie.rating, json["rating"]) + def test_response_body_is_a_dict_not_a_list(self): + """ + The response body should be a JSON object (e.g. ``{"id": 1}``), not + a single-item list (e.g. ``[{"id": 1}]``), so a client can read the + id straight off the parsed response without unwrapping a list. + + https://github.com/piccolo-orm/piccolo_api/issues/211 + """ + client = TestClient(PiccoloCRUD(table=Movie, read_only=False)) + + response = client.post("/", json={"name": "Star Wars", "rating": 93}) + self.assertEqual(response.status_code, 201) + + body = response.json() + self.assertIsInstance(body, dict) + + movie = Movie.objects().first().run_sync() + self.assertEqual(body["id"], movie.id) + def test_post_user_success(self): client = TestClient(PiccoloCRUD(table=BaseUser, read_only=False)) diff --git a/tests/fastapi/test_fastapi_endpoints.py b/tests/fastapi/test_fastapi_endpoints.py index b5cd0d51..8688e621 100644 --- a/tests/fastapi/test_fastapi_endpoints.py +++ b/tests/fastapi/test_fastapi_endpoints.py @@ -238,7 +238,7 @@ def test_post(self): "/movies/", json={"name": "Star Wars", "rating": 93} ) self.assertEqual(response.status_code, 201) - self.assertEqual(response.json(), [{"id": 2}]) + self.assertEqual(response.json(), {"id": 2}) def test_put(self): client = TestClient(app)