mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-113149: Improve error message when JSON has trailing comma (GH-113227)
This commit is contained in:
parent
21d52995ea
commit
cfa25fe3e3
4 changed files with 28 additions and 3 deletions
|
@ -200,10 +200,13 @@ def JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook,
|
||||||
break
|
break
|
||||||
elif nextchar != ',':
|
elif nextchar != ',':
|
||||||
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
|
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
|
||||||
|
comma_idx = end - 1
|
||||||
end = _w(s, end).end()
|
end = _w(s, end).end()
|
||||||
nextchar = s[end:end + 1]
|
nextchar = s[end:end + 1]
|
||||||
end += 1
|
end += 1
|
||||||
if nextchar != '"':
|
if nextchar != '"':
|
||||||
|
if nextchar == '}':
|
||||||
|
raise JSONDecodeError("Illegal trailing comma before end of object", s, comma_idx)
|
||||||
raise JSONDecodeError(
|
raise JSONDecodeError(
|
||||||
"Expecting property name enclosed in double quotes", s, end - 1)
|
"Expecting property name enclosed in double quotes", s, end - 1)
|
||||||
if object_pairs_hook is not None:
|
if object_pairs_hook is not None:
|
||||||
|
@ -240,13 +243,17 @@ def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
|
||||||
break
|
break
|
||||||
elif nextchar != ',':
|
elif nextchar != ',':
|
||||||
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
|
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
|
||||||
|
comma_idx = end - 1
|
||||||
try:
|
try:
|
||||||
if s[end] in _ws:
|
if s[end] in _ws:
|
||||||
end += 1
|
end += 1
|
||||||
if s[end] in _ws:
|
if s[end] in _ws:
|
||||||
end = _w(s, end + 1).end()
|
end = _w(s, end + 1).end()
|
||||||
|
nextchar = s[end:end + 1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
if nextchar == ']':
|
||||||
|
raise JSONDecodeError("Illegal trailing comma before end of array", s, comma_idx)
|
||||||
|
|
||||||
return values, end
|
return values, end
|
||||||
|
|
||||||
|
|
|
@ -143,11 +143,11 @@ class TestFail:
|
||||||
('{"spam":[}', 'Expecting value', 9),
|
('{"spam":[}', 'Expecting value', 9),
|
||||||
('[42:', "Expecting ',' delimiter", 3),
|
('[42:', "Expecting ',' delimiter", 3),
|
||||||
('[42 "spam"', "Expecting ',' delimiter", 4),
|
('[42 "spam"', "Expecting ',' delimiter", 4),
|
||||||
('[42,]', 'Expecting value', 4),
|
('[42,]', "Illegal trailing comma before end of array", 3),
|
||||||
('{"spam":[42}', "Expecting ',' delimiter", 11),
|
('{"spam":[42}', "Expecting ',' delimiter", 11),
|
||||||
('["]', 'Unterminated string starting at', 1),
|
('["]', 'Unterminated string starting at', 1),
|
||||||
('["spam":', "Expecting ',' delimiter", 7),
|
('["spam":', "Expecting ',' delimiter", 7),
|
||||||
('["spam",]', 'Expecting value', 8),
|
('["spam",]', "Illegal trailing comma before end of array", 7),
|
||||||
('{:', 'Expecting property name enclosed in double quotes', 1),
|
('{:', 'Expecting property name enclosed in double quotes', 1),
|
||||||
('{,', 'Expecting property name enclosed in double quotes', 1),
|
('{,', 'Expecting property name enclosed in double quotes', 1),
|
||||||
('{42', 'Expecting property name enclosed in double quotes', 1),
|
('{42', 'Expecting property name enclosed in double quotes', 1),
|
||||||
|
@ -159,7 +159,9 @@ class TestFail:
|
||||||
('[{"spam":]', 'Expecting value', 9),
|
('[{"spam":]', 'Expecting value', 9),
|
||||||
('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
|
('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
|
||||||
('[{"spam":42]', "Expecting ',' delimiter", 11),
|
('[{"spam":42]', "Expecting ',' delimiter", 11),
|
||||||
('{"spam":42,}', 'Expecting property name enclosed in double quotes', 11),
|
('{"spam":42,}', "Illegal trailing comma before end of object", 10),
|
||||||
|
('{"spam":42 , }', "Illegal trailing comma before end of object", 11),
|
||||||
|
('[123 , ]', "Illegal trailing comma before end of array", 6),
|
||||||
]
|
]
|
||||||
for data, msg, idx in test_cases:
|
for data, msg, idx in test_cases:
|
||||||
with self.assertRaises(self.JSONDecodeError) as cm:
|
with self.assertRaises(self.JSONDecodeError) as cm:
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Improve error message when a JSON array or object contains a trailing comma.
|
||||||
|
Patch by Carson Radtke.
|
|
@ -662,6 +662,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss
|
||||||
PyObject *key = NULL;
|
PyObject *key = NULL;
|
||||||
int has_pairs_hook = (s->object_pairs_hook != Py_None);
|
int has_pairs_hook = (s->object_pairs_hook != Py_None);
|
||||||
Py_ssize_t next_idx;
|
Py_ssize_t next_idx;
|
||||||
|
Py_ssize_t comma_idx;
|
||||||
|
|
||||||
str = PyUnicode_DATA(pystr);
|
str = PyUnicode_DATA(pystr);
|
||||||
kind = PyUnicode_KIND(pystr);
|
kind = PyUnicode_KIND(pystr);
|
||||||
|
@ -741,10 +742,16 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss
|
||||||
raise_errmsg("Expecting ',' delimiter", pystr, idx);
|
raise_errmsg("Expecting ',' delimiter", pystr, idx);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
comma_idx = idx;
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
/* skip whitespace after , delimiter */
|
/* skip whitespace after , delimiter */
|
||||||
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
|
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
|
||||||
|
|
||||||
|
if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == '}') {
|
||||||
|
raise_errmsg("Illegal trailing comma before end of object", pystr, comma_idx);
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,6 +792,7 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi
|
||||||
PyObject *val = NULL;
|
PyObject *val = NULL;
|
||||||
PyObject *rval;
|
PyObject *rval;
|
||||||
Py_ssize_t next_idx;
|
Py_ssize_t next_idx;
|
||||||
|
Py_ssize_t comma_idx;
|
||||||
|
|
||||||
rval = PyList_New(0);
|
rval = PyList_New(0);
|
||||||
if (rval == NULL)
|
if (rval == NULL)
|
||||||
|
@ -822,10 +830,16 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi
|
||||||
raise_errmsg("Expecting ',' delimiter", pystr, idx);
|
raise_errmsg("Expecting ',' delimiter", pystr, idx);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
comma_idx = idx;
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
/* skip whitespace after , */
|
/* skip whitespace after , */
|
||||||
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
|
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
|
||||||
|
|
||||||
|
if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == ']') {
|
||||||
|
raise_errmsg("Illegal trailing comma before end of array", pystr, comma_idx);
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue