diff -r 3fbfa61634de Lib/json/decoder.py --- a/Lib/json/decoder.py Thu Jul 19 00:14:35 2012 -0500 +++ b/Lib/json/decoder.py Thu Jul 19 14:37:51 2012 +0300 @@ -343,29 +343,30 @@ self.memo = {} self.scan_once = scanner.make_scanner(self) - def decode(self, s, _w=WHITESPACE.match): """Return the Python representation of ``s`` (a ``str`` instance containing a JSON document). """ - obj, end = self.raw_decode(s, idx=_w(s, 0).end()) + obj, end = self.raw_decode(s) end = _w(s, end).end() if end != len(s): raise ValueError(errmsg("Extra data", s, end, len(s))) return obj - def raw_decode(self, s, idx=0): + def raw_decode(self, s, idx=0, _w=WHITESPACE.match): """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. + 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. """ try: - obj, end = self.scan_once(s, idx) + obj, end = self.scan_once(s, idx=_w(s, idx).end()) except StopIteration: raise ValueError("No JSON object could be decoded") return obj, end diff -r 3fbfa61634de Lib/test/json_tests/test_decode.py --- a/Lib/test/json_tests/test_decode.py Thu Jul 19 00:14:35 2012 -0500 +++ b/Lib/test/json_tests/test_decode.py Thu Jul 19 14:37:51 2012 +0300 @@ -55,5 +55,14 @@ self.check_keys_reuse(s, self.json.decoder.JSONDecoder().decode) +class TestRawDecode: + def test_whitespace(self): + decoder = self.json.JSONDecoder() + self.assertEqual(decoder.raw_decode(' {}'), ({}, 3)) + self.assertEqual(decoder.raw_decode(' []'), ([], 3)) + self.assertEqual(decoder.raw_decode(' ""'), ("", 3)) + class TestPyDecode(TestDecode, PyTest): pass class TestCDecode(TestDecode, CTest): pass +class TestPyRawDecode(TestRawDecode, PyTest): pass +class TestCRawDecode(TestRawDecode, CTest): pass