1import decimal 2from io import StringIO 3from collections import OrderedDict 4from test.test_json import PyTest, CTest 5from test import support 6 7 8class TestDecode: 9 def test_decimal(self): 10 rval = self.loads('1.1', parse_float=decimal.Decimal) 11 self.assertTrue(isinstance(rval, decimal.Decimal)) 12 self.assertEqual(rval, decimal.Decimal('1.1')) 13 14 def test_float(self): 15 rval = self.loads('1', parse_int=float) 16 self.assertTrue(isinstance(rval, float)) 17 self.assertEqual(rval, 1.0) 18 19 def test_empty_objects(self): 20 self.assertEqual(self.loads('{}'), {}) 21 self.assertEqual(self.loads('[]'), []) 22 self.assertEqual(self.loads('""'), "") 23 24 def test_object_pairs_hook(self): 25 s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' 26 p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), 27 ("qrt", 5), ("pad", 6), ("hoy", 7)] 28 self.assertEqual(self.loads(s), eval(s)) 29 self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) 30 self.assertEqual(self.json.load(StringIO(s), 31 object_pairs_hook=lambda x: x), p) 32 od = self.loads(s, object_pairs_hook=OrderedDict) 33 self.assertEqual(od, OrderedDict(p)) 34 self.assertEqual(type(od), OrderedDict) 35 # the object_pairs_hook takes priority over the object_hook 36 self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, 37 object_hook=lambda x: None), 38 OrderedDict(p)) 39 # check that empty object literals work (see #17368) 40 self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict), 41 OrderedDict()) 42 self.assertEqual(self.loads('{"empty": {}}', 43 object_pairs_hook=OrderedDict), 44 OrderedDict([('empty', OrderedDict())])) 45 46 def test_decoder_optimizations(self): 47 # Several optimizations were made that skip over calls to 48 # the whitespace regex, so this test is designed to try and 49 # exercise the uncommon cases. The array cases are already covered. 50 rval = self.loads('{ "key" : "value" , "k":"v" }') 51 self.assertEqual(rval, {"key":"value", "k":"v"}) 52 53 def check_keys_reuse(self, source, loads): 54 rval = loads(source) 55 (a, b), (c, d) = sorted(rval[0]), sorted(rval[1]) 56 self.assertIs(a, c) 57 self.assertIs(b, d) 58 59 def test_keys_reuse(self): 60 s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' 61 self.check_keys_reuse(s, self.loads) 62 decoder = self.json.decoder.JSONDecoder() 63 self.check_keys_reuse(s, decoder.decode) 64 self.assertFalse(decoder.memo) 65 66 def test_extra_data(self): 67 s = '[1, 2, 3]5' 68 msg = 'Extra data' 69 self.assertRaisesRegex(self.JSONDecodeError, msg, self.loads, s) 70 71 def test_invalid_escape(self): 72 s = '["abc\\y"]' 73 msg = 'escape' 74 self.assertRaisesRegex(self.JSONDecodeError, msg, self.loads, s) 75 76 def test_invalid_input_type(self): 77 msg = 'the JSON object must be str' 78 for value in [1, 3.14, [], {}, None]: 79 self.assertRaisesRegex(TypeError, msg, self.loads, value) 80 81 def test_string_with_utf8_bom(self): 82 # see #18958 83 bom_json = "[1,2,3]".encode('utf-8-sig').decode('utf-8') 84 with self.assertRaises(self.JSONDecodeError) as cm: 85 self.loads(bom_json) 86 self.assertIn('BOM', str(cm.exception)) 87 with self.assertRaises(self.JSONDecodeError) as cm: 88 self.json.load(StringIO(bom_json)) 89 self.assertIn('BOM', str(cm.exception)) 90 # make sure that the BOM is not detected in the middle of a string 91 bom_in_str = '"{}"'.format(''.encode('utf-8-sig').decode('utf-8')) 92 self.assertEqual(self.loads(bom_in_str), '\ufeff') 93 self.assertEqual(self.json.load(StringIO(bom_in_str)), '\ufeff') 94 95 def test_negative_index(self): 96 d = self.json.JSONDecoder() 97 self.assertRaises(ValueError, d.raw_decode, 'a'*42, -50000) 98 99 def test_limit_int(self): 100 maxdigits = 5000 101 with support.adjust_int_max_str_digits(maxdigits): 102 self.loads('1' * maxdigits) 103 with self.assertRaises(ValueError): 104 self.loads('1' * (maxdigits + 1)) 105 106 107class TestPyDecode(TestDecode, PyTest): pass 108class TestCDecode(TestDecode, CTest): pass 109