-
-
Notifications
You must be signed in to change notification settings - Fork 709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Figure out design for JSON errors (consider RFC 7807) #1875
Comments
I started a conversation about JSON error standards on Mastodon here: https://fedi.simonwillison.net/web/@simon/109338725610487457 Quite a few people pointed to this RFC independently. |
Here's the most relevant example from the RFC spec:
{
"age": 42.3,
"profile": {
"color": "yellow"
}
}
{
"type": "https://example.net/validation-error",
"title": "Your request is not valid.",
"errors": [
{
"detail": "must be a positive integer",
"pointer": "#/age"
},
{
"detail": "must be 'green', 'red' or 'blue'",
"pointer": "#/profile/color"
}
]
} |
That's using JSON Pointer: https://www.rfc-editor.org/rfc/rfc6901 There'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. So I think I'll end up hand-rolling this. |
Spec looks pretty simple:
|
Worth noting this bit in RFC 7807:
So the list of It fits what I need to do though, so I'm inclined to stick with it anyway. |
Rough initial prototype: diff --git a/datasette/views/table.py b/datasette/views/table.py
index 8b987221..518ac578 100644
--- a/datasette/views/table.py
+++ b/datasette/views/table.py
@@ -1103,19 +1103,30 @@ class TableInsertView(BaseView):
except json.JSONDecodeError as e:
return _errors(["Invalid JSON: {}".format(e)])
if not isinstance(data, dict):
- return _errors(["JSON must be a dictionary"])
+ return _errors([{"detail": "JSON must be a dictionary", "pointer": "#/"}])
keys = data.keys()
# keys must contain "row" or "rows"
if "row" not in keys and "rows" not in keys:
return _errors(['JSON must have one or other of "row" or "rows"'])
rows = []
+ was_single_row = False
if "row" in keys:
if "rows" in keys:
- return _errors(['Cannot use "row" and "rows" at the same time'])
+ return _errors(
+ [
+ {
+ "detail": 'Cannot use "row" and "rows" at the same time',
+ "pointer": "#/row",
+ }
+ ]
+ )
+ was_single_row = True
row = data["row"]
if not isinstance(row, dict):
- return _errors(['"row" must be a dictionary'])
+ return _errors(
+ [{"detail": '"row" must be a dictionary', "pointer": "#/row"}]
+ )
rows = [row]
data["return"] = True
else:
@@ -1152,9 +1163,12 @@ class TableInsertView(BaseView):
invalid_columns = set(row.keys()) - columns
if invalid_columns:
errors.append(
- "Row {} has invalid columns: {}".format(
- i, ", ".join(sorted(invalid_columns))
- )
+ {
+ "detail": "Invalid columns: {}".format(
+ ", ".join(sorted(invalid_columns))
+ ),
+ "pointer": "#/blah/",
+ }
)
if errors:
return _errors(errors) |
https://datatracker.ietf.org/doc/draft-ietf-httpapi-rfc7807bis/ is a brand new standard.
Since I need a neat, predictable format for my JSON errors, maybe I should use this one?
The text was updated successfully, but these errors were encountered: