diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py index 2422c6a..8ee3b94 100644 --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -346,13 +346,18 @@ class JSONDecoder(object): """Decode a JSON document from ``s`` (a ``str`` beginning with a JSON document) and return a 2-tuple of the Python representation and the index in ``s`` where the document ended. + Whitespace at the beginning of the document will be ignored. + + Optionally, ``idx`` can be used to specify an offset in ``s`` + where the document begins. This can be used to decode a JSON document from a string that may have extraneous data at the end. """ + _w = WHITESPACE.match try: - obj, end = self.scan_once(s, idx) + obj, end = self.scan_once(s, idx=_w(s, idx).end()) except StopIteration as err: raise JSONDecodeError("Expecting value", s, err.value) from None return obj, end diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index 7e568be..856d6c4 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -93,5 +93,22 @@ class TestDecode: d = self.json.JSONDecoder() self.assertRaises(ValueError, d.raw_decode, 'a'*42, -50000) + +class TestRawDecode: + def test_whitespace(self): + decoder = self.json.JSONDecoder() + self.assertEqual(decoder.raw_decode(' {}'), ({}, 3)) + self.assertEqual(decoder.raw_decode(' []'), ([], 4)) + self.assertEqual(decoder.raw_decode(' ""'), ('', 5)) + s = ' { "key" : "value" , "k":"v" } \n' \ + ' { "key": "value", "k" :"v"} ' + val1, n1 = decoder.raw_decode(s) + val2, n2 = decoder.raw_decode(s[n1:]) + self.assertEqual(val1, {"key":"value", "k":"v"}) + self.assertEqual(val2, {"key":"value", "k":"v"}) + + class TestPyDecode(TestDecode, PyTest): pass class TestCDecode(TestDecode, CTest): pass +class TestPyRawDecode(TestRawDecode, PyTest): pass +class TestCRawDecode(TestRawDecode, CTest): pass