{"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1313114283", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1313114283, "node_id": "IC_kwDOBm6k_c5ORIir", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-14T05:20:00Z", "updated_at": "2022-11-14T05:20:00Z", "author_association": "OWNER", "body": "I started a conversation about JSON error standards on Mastodon here: https://fedi.simonwillison.net/web/@simon/109338725610487457\r\n\r\nQuite a few people pointed to this RFC independently.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1314488010", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1314488010, "node_id": "IC_kwDOBm6k_c5OWX7K", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-14T22:21:43Z", "updated_at": "2022-11-14T22:21:43Z", "author_association": "OWNER", "body": "Here's the most relevant example from the RFC spec:\r\n```\r\n POST /details HTTP/1.1\r\n Host: account.example.com\r\n Accept: application/json\r\n```\r\n```json\r\n {\r\n \"age\": 42.3,\r\n \"profile\": {\r\n \"color\": \"yellow\"\r\n }\r\n }\r\n```\r\n```\r\n HTTP/1.1 400 Bad Request\r\n Content-Type: application/problem+json\r\n Content-Language: en\r\n```\r\n```json\r\n{\r\n \"type\": \"https://example.net/validation-error\",\r\n \"title\": \"Your request is not valid.\",\r\n \"errors\": [\r\n {\r\n \"detail\": \"must be a positive integer\",\r\n \"pointer\": \"#/age\"\r\n },\r\n {\r\n \"detail\": \"must be 'green', 'red' or 'blue'\",\r\n \"pointer\": \"#/profile/color\"\r\n }\r\n ]\r\n}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1314491150", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1314491150, "node_id": "IC_kwDOBm6k_c5OWYsO", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-14T22:25:20Z", "updated_at": "2022-11-14T22:25:20Z", "author_association": "OWNER", "body": "That's using JSON Pointer: https://www.rfc-editor.org/rfc/rfc6901\r\n\r\nThere's a Python library for that here https://github.com/stefankoegl/python-json-pointer/blob/master/jsonpointer.py - which looks simple and clean and well maintained and documented, but it only handles the \"what is at this pointer within this JSON object\" case - I need to generate the correct JSON pointer to explain where my error is.\r\n\r\nSo I think I'll end up hand-rolling this.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1314491884", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1314491884, "node_id": "IC_kwDOBm6k_c5OWY3s", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-14T22:26:11Z", "updated_at": "2022-11-14T22:26:54Z", "author_association": "OWNER", "body": "Spec looks pretty simple:\r\n\r\n> A JSON Pointer is a Unicode string (see [RFC4627], Section 3)\r\n> containing a sequence of zero or more reference tokens, each prefixed\r\n> by a `/` (%x2F) character.\r\n> \r\n> Because the characters `~` (%x7E) and `/` (%x2F) have special\r\n> meanings in JSON Pointer, `~` needs to be encoded as `~0` and `/`\r\n> needs to be encoded as `~1` when these characters appear in a\r\n> reference token.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1314545407", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1314545407, "node_id": "IC_kwDOBm6k_c5OWl7_", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-14T23:30:34Z", "updated_at": "2022-11-14T23:30:34Z", "author_association": "OWNER", "body": "TIL: https://til.simonwillison.net/json/json-pointer", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1314615592", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1314615592, "node_id": "IC_kwDOBm6k_c5OW3Eo", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-15T01:04:28Z", "updated_at": "2022-11-15T01:04:28Z", "author_association": "OWNER", "body": "Worth noting this bit in RFC 7807:\r\n\r\n> The fictional problem type here defines the \"errors\" extension, an\r\n> array that describes the details of each validation error. Each\r\n> member is an object containing \"detail\" to describe the issue, and\r\n> \"pointer\" to locate the problem within the request's content using a\r\n> JSON Pointer [JSON-POINTER].\r\n\r\nSo the list of `\"errors\"` with JSON Pointer isn't technically part of the spec, it's an imaginary extension.\r\n\r\nIt fits what I need to do though, so I'm inclined to stick with it anyway.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1875#issuecomment-1314620086", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1875", "id": 1314620086, "node_id": "IC_kwDOBm6k_c5OW4K2", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-11-15T01:09:56Z", "updated_at": "2022-11-15T01:09:56Z", "author_association": "OWNER", "body": "Rough initial prototype:\r\n```diff\r\ndiff --git a/datasette/views/table.py b/datasette/views/table.py\r\nindex 8b987221..518ac578 100644\r\n--- a/datasette/views/table.py\r\n+++ b/datasette/views/table.py\r\n@@ -1103,19 +1103,30 @@ class TableInsertView(BaseView):\r\n except json.JSONDecodeError as e:\r\n return _errors([\"Invalid JSON: {}\".format(e)])\r\n if not isinstance(data, dict):\r\n- return _errors([\"JSON must be a dictionary\"])\r\n+ return _errors([{\"detail\": \"JSON must be a dictionary\", \"pointer\": \"#/\"}])\r\n keys = data.keys()\r\n \r\n # keys must contain \"row\" or \"rows\"\r\n if \"row\" not in keys and \"rows\" not in keys:\r\n return _errors(['JSON must have one or other of \"row\" or \"rows\"'])\r\n rows = []\r\n+ was_single_row = False\r\n if \"row\" in keys:\r\n if \"rows\" in keys:\r\n- return _errors(['Cannot use \"row\" and \"rows\" at the same time'])\r\n+ return _errors(\r\n+ [\r\n+ {\r\n+ \"detail\": 'Cannot use \"row\" and \"rows\" at the same time',\r\n+ \"pointer\": \"#/row\",\r\n+ }\r\n+ ]\r\n+ )\r\n+ was_single_row = True\r\n row = data[\"row\"]\r\n if not isinstance(row, dict):\r\n- return _errors(['\"row\" must be a dictionary'])\r\n+ return _errors(\r\n+ [{\"detail\": '\"row\" must be a dictionary', \"pointer\": \"#/row\"}]\r\n+ )\r\n rows = [row]\r\n data[\"return\"] = True\r\n else:\r\n@@ -1152,9 +1163,12 @@ class TableInsertView(BaseView):\r\n invalid_columns = set(row.keys()) - columns\r\n if invalid_columns:\r\n errors.append(\r\n- \"Row {} has invalid columns: {}\".format(\r\n- i, \", \".join(sorted(invalid_columns))\r\n- )\r\n+ {\r\n+ \"detail\": \"Invalid columns: {}\".format(\r\n+ \", \".join(sorted(invalid_columns))\r\n+ ),\r\n+ \"pointer\": \"#/blah/\",\r\n+ }\r\n )\r\n if errors:\r\n return _errors(errors)\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1430797211, "label": "Figure out design for JSON errors (consider RFC 7807)"}, "performed_via_github_app": null}