1
0
mirror of https://github.com/ultrajson/ultrajson.git synced 2024-11-22 23:52:08 +01:00

Raise JSONDecodeError in place of ValueError on failed decode (#498)

So as to match the behaviour of Python's json library.
Fixes #497
This commit is contained in:
JustAnotherArchivist 2022-02-05 20:39:05 +00:00 committed by GitHub
parent d5b701f209
commit 316d384f41
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 33 deletions

@ -38,6 +38,7 @@ http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
#include <Python.h>
#include <ultrajson.h>
#include "ujson.h"
//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
@ -187,7 +188,7 @@ PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs)
/*
FIXME: It's possible to give a much nicer error message here with actual failing element in input etc*/
PyErr_Format (PyExc_ValueError, "%s", decoder.errorStr);
PyErr_Format (JSONDecodeError, "%s", decoder.errorStr);
if (ret)
{

@ -38,6 +38,7 @@ http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
#include <Python.h>
#include "version.h"
#include "ujson.h"
/* objToJSON */
PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs);
@ -51,6 +52,8 @@ PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs);
/* JSONFileToObj */
PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs);
PyObject* JSONDecodeError;
#define ENCODER_HELP_TEXT "Use ensure_ascii=false to output UTF-8. " \
"Set encode_html_chars=True to encode < > & as unicode escape sequences. "\
@ -188,5 +191,15 @@ PyMODINIT_FUNC PyInit_ujson(void)
PyErr_Clear();
#endif
JSONDecodeError = PyErr_NewException("ujson.JSONDecodeError", PyExc_ValueError, NULL);
Py_XINCREF(JSONDecodeError);
if (PyModule_AddObject(module, "JSONDecodeError", JSONDecodeError) < 0)
{
Py_XDECREF(JSONDecodeError);
Py_CLEAR(JSONDecodeError);
Py_DECREF(module);
return NULL;
}
return module;
}

1
python/ujson.h Normal file

@ -0,0 +1 @@
extern PyObject* JSONDecodeError;

@ -555,46 +555,46 @@ def test_decode_numeric_int_exp(test_input):
@pytest.mark.parametrize(
"test_input, expected",
[
('{{1337:""}}', ValueError), # broken dict key type leak test
('{{"key":"}', ValueError), # broken dict leak test
('{{"key":"}', ValueError), # broken dict leak test
("[[[true", ValueError), # broken list leak test
('{{1337:""}}', ujson.JSONDecodeError), # broken dict key type leak test
('{{"key":"}', ujson.JSONDecodeError), # broken dict leak test
('{{"key":"}', ujson.JSONDecodeError), # broken dict leak test
("[[[true", ujson.JSONDecodeError), # broken list leak test
],
)
def test_decode_range_raises(test_input, expected):
for x in range(1000):
with pytest.raises(ValueError):
with pytest.raises(expected):
ujson.decode(test_input)
@pytest.mark.parametrize(
"test_input, expected",
[
("fdsa sda v9sa fdsa", ValueError), # jibberish
("[", ValueError), # broken array start
("{", ValueError), # broken object start
("]", ValueError), # broken array end
("}", ValueError), # broken object end
('{"one":1,}', ValueError), # object trailing comma fail
('"TESTING', ValueError), # string unterminated
('"TESTING\\"', ValueError), # string bad escape
("tru", ValueError), # true broken
("fa", ValueError), # false broken
("n", ValueError), # null broken
("{{{{31337}}}}", ValueError), # dict with no key
('{{{{"key"}}}}', ValueError), # dict with no colon or value
('{{{{"key":}}}}', ValueError), # dict with no value
("[31337,]", ValueError), # array trailing comma fail
("[,31337]", ValueError), # array leading comma fail
("[,]", ValueError), # array only comma fail
("[]]", ValueError), # array unmatched bracket fail
("18446744073709551616", ValueError), # too big value
("-90223372036854775809", ValueError), # too small value
("18446744073709551616", ValueError), # very too big value
("-90223372036854775809", ValueError), # very too small value
("{}\n\t a", ValueError), # with trailing non whitespaces
("[18446744073709551616]", ValueError), # array with big int
('{"age", 44}', ValueError), # read bad object syntax
("fdsa sda v9sa fdsa", ujson.JSONDecodeError), # jibberish
("[", ujson.JSONDecodeError), # broken array start
("{", ujson.JSONDecodeError), # broken object start
("]", ujson.JSONDecodeError), # broken array end
("}", ujson.JSONDecodeError), # broken object end
('{"one":1,}', ujson.JSONDecodeError), # object trailing comma fail
('"TESTING', ujson.JSONDecodeError), # string unterminated
('"TESTING\\"', ujson.JSONDecodeError), # string bad escape
("tru", ujson.JSONDecodeError), # true broken
("fa", ujson.JSONDecodeError), # false broken
("n", ujson.JSONDecodeError), # null broken
("{{{{31337}}}}", ujson.JSONDecodeError), # dict with no key
('{{{{"key"}}}}', ujson.JSONDecodeError), # dict with no colon or value
('{{{{"key":}}}}', ujson.JSONDecodeError), # dict with no value
("[31337,]", ujson.JSONDecodeError), # array trailing comma fail
("[,31337]", ujson.JSONDecodeError), # array leading comma fail
("[,]", ujson.JSONDecodeError), # array only comma fail
("[]]", ujson.JSONDecodeError), # array unmatched bracket fail
("18446744073709551616", ujson.JSONDecodeError), # too big value
("-90223372036854775809", ujson.JSONDecodeError), # too small value
("18446744073709551616", ujson.JSONDecodeError), # very too big value
("-90223372036854775809", ujson.JSONDecodeError), # very too small value
("{}\n\t a", ujson.JSONDecodeError), # with trailing non whitespaces
("[18446744073709551616]", ujson.JSONDecodeError), # array with big int
('{"age", 44}', ujson.JSONDecodeError), # read bad object syntax
],
)
def test_decode_raises(test_input, expected):
@ -605,8 +605,8 @@ def test_decode_raises(test_input, expected):
@pytest.mark.parametrize(
"test_input, expected",
[
("[", ValueError), # array depth too big
("{", ValueError), # object depth too big
("[", ujson.JSONDecodeError), # array depth too big
("{", ujson.JSONDecodeError), # object depth too big
],
)
def test_decode_raises_for_long_input(test_input, expected):
@ -614,6 +614,10 @@ def test_decode_raises_for_long_input(test_input, expected):
ujson.decode(test_input * (1024 * 1024))
def test_decode_exception_is_value_error():
assert issubclass(ujson.JSONDecodeError, ValueError)
@pytest.mark.parametrize(
"test_input, expected",
[