1*cda5da8dSAndroid Build Coastguard Worker"""Implementation of JSONDecoder 2*cda5da8dSAndroid Build Coastguard Worker""" 3*cda5da8dSAndroid Build Coastguard Workerimport re 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Workerfrom json import scanner 6*cda5da8dSAndroid Build Coastguard Workertry: 7*cda5da8dSAndroid Build Coastguard Worker from _json import scanstring as c_scanstring 8*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 9*cda5da8dSAndroid Build Coastguard Worker c_scanstring = None 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard Worker__all__ = ['JSONDecoder', 'JSONDecodeError'] 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard WorkerFLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard WorkerNaN = float('nan') 16*cda5da8dSAndroid Build Coastguard WorkerPosInf = float('inf') 17*cda5da8dSAndroid Build Coastguard WorkerNegInf = float('-inf') 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Worker 20*cda5da8dSAndroid Build Coastguard Workerclass JSONDecodeError(ValueError): 21*cda5da8dSAndroid Build Coastguard Worker """Subclass of ValueError with the following additional properties: 22*cda5da8dSAndroid Build Coastguard Worker 23*cda5da8dSAndroid Build Coastguard Worker msg: The unformatted error message 24*cda5da8dSAndroid Build Coastguard Worker doc: The JSON document being parsed 25*cda5da8dSAndroid Build Coastguard Worker pos: The start index of doc where parsing failed 26*cda5da8dSAndroid Build Coastguard Worker lineno: The line corresponding to pos 27*cda5da8dSAndroid Build Coastguard Worker colno: The column corresponding to pos 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard Worker """ 30*cda5da8dSAndroid Build Coastguard Worker # Note that this exception is used from _json 31*cda5da8dSAndroid Build Coastguard Worker def __init__(self, msg, doc, pos): 32*cda5da8dSAndroid Build Coastguard Worker lineno = doc.count('\n', 0, pos) + 1 33*cda5da8dSAndroid Build Coastguard Worker colno = pos - doc.rfind('\n', 0, pos) 34*cda5da8dSAndroid Build Coastguard Worker errmsg = '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos) 35*cda5da8dSAndroid Build Coastguard Worker ValueError.__init__(self, errmsg) 36*cda5da8dSAndroid Build Coastguard Worker self.msg = msg 37*cda5da8dSAndroid Build Coastguard Worker self.doc = doc 38*cda5da8dSAndroid Build Coastguard Worker self.pos = pos 39*cda5da8dSAndroid Build Coastguard Worker self.lineno = lineno 40*cda5da8dSAndroid Build Coastguard Worker self.colno = colno 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 43*cda5da8dSAndroid Build Coastguard Worker return self.__class__, (self.msg, self.doc, self.pos) 44*cda5da8dSAndroid Build Coastguard Worker 45*cda5da8dSAndroid Build Coastguard Worker 46*cda5da8dSAndroid Build Coastguard Worker_CONSTANTS = { 47*cda5da8dSAndroid Build Coastguard Worker '-Infinity': NegInf, 48*cda5da8dSAndroid Build Coastguard Worker 'Infinity': PosInf, 49*cda5da8dSAndroid Build Coastguard Worker 'NaN': NaN, 50*cda5da8dSAndroid Build Coastguard Worker} 51*cda5da8dSAndroid Build Coastguard Worker 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard WorkerSTRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) 54*cda5da8dSAndroid Build Coastguard WorkerBACKSLASH = { 55*cda5da8dSAndroid Build Coastguard Worker '"': '"', '\\': '\\', '/': '/', 56*cda5da8dSAndroid Build Coastguard Worker 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 57*cda5da8dSAndroid Build Coastguard Worker} 58*cda5da8dSAndroid Build Coastguard Worker 59*cda5da8dSAndroid Build Coastguard Workerdef _decode_uXXXX(s, pos): 60*cda5da8dSAndroid Build Coastguard Worker esc = s[pos + 1:pos + 5] 61*cda5da8dSAndroid Build Coastguard Worker if len(esc) == 4 and esc[1] not in 'xX': 62*cda5da8dSAndroid Build Coastguard Worker try: 63*cda5da8dSAndroid Build Coastguard Worker return int(esc, 16) 64*cda5da8dSAndroid Build Coastguard Worker except ValueError: 65*cda5da8dSAndroid Build Coastguard Worker pass 66*cda5da8dSAndroid Build Coastguard Worker msg = "Invalid \\uXXXX escape" 67*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError(msg, s, pos) 68*cda5da8dSAndroid Build Coastguard Worker 69*cda5da8dSAndroid Build Coastguard Workerdef py_scanstring(s, end, strict=True, 70*cda5da8dSAndroid Build Coastguard Worker _b=BACKSLASH, _m=STRINGCHUNK.match): 71*cda5da8dSAndroid Build Coastguard Worker """Scan the string s for a JSON string. End is the index of the 72*cda5da8dSAndroid Build Coastguard Worker character in s after the quote that started the JSON string. 73*cda5da8dSAndroid Build Coastguard Worker Unescapes all valid JSON string escape sequences and raises ValueError 74*cda5da8dSAndroid Build Coastguard Worker on attempt to decode an invalid string. If strict is False then literal 75*cda5da8dSAndroid Build Coastguard Worker control characters are allowed in the string. 76*cda5da8dSAndroid Build Coastguard Worker 77*cda5da8dSAndroid Build Coastguard Worker Returns a tuple of the decoded string and the index of the character in s 78*cda5da8dSAndroid Build Coastguard Worker after the end quote.""" 79*cda5da8dSAndroid Build Coastguard Worker chunks = [] 80*cda5da8dSAndroid Build Coastguard Worker _append = chunks.append 81*cda5da8dSAndroid Build Coastguard Worker begin = end - 1 82*cda5da8dSAndroid Build Coastguard Worker while 1: 83*cda5da8dSAndroid Build Coastguard Worker chunk = _m(s, end) 84*cda5da8dSAndroid Build Coastguard Worker if chunk is None: 85*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Unterminated string starting at", s, begin) 86*cda5da8dSAndroid Build Coastguard Worker end = chunk.end() 87*cda5da8dSAndroid Build Coastguard Worker content, terminator = chunk.groups() 88*cda5da8dSAndroid Build Coastguard Worker # Content is contains zero or more unescaped string characters 89*cda5da8dSAndroid Build Coastguard Worker if content: 90*cda5da8dSAndroid Build Coastguard Worker _append(content) 91*cda5da8dSAndroid Build Coastguard Worker # Terminator is the end of string, a literal control character, 92*cda5da8dSAndroid Build Coastguard Worker # or a backslash denoting that an escape sequence follows 93*cda5da8dSAndroid Build Coastguard Worker if terminator == '"': 94*cda5da8dSAndroid Build Coastguard Worker break 95*cda5da8dSAndroid Build Coastguard Worker elif terminator != '\\': 96*cda5da8dSAndroid Build Coastguard Worker if strict: 97*cda5da8dSAndroid Build Coastguard Worker #msg = "Invalid control character %r at" % (terminator,) 98*cda5da8dSAndroid Build Coastguard Worker msg = "Invalid control character {0!r} at".format(terminator) 99*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError(msg, s, end) 100*cda5da8dSAndroid Build Coastguard Worker else: 101*cda5da8dSAndroid Build Coastguard Worker _append(terminator) 102*cda5da8dSAndroid Build Coastguard Worker continue 103*cda5da8dSAndroid Build Coastguard Worker try: 104*cda5da8dSAndroid Build Coastguard Worker esc = s[end] 105*cda5da8dSAndroid Build Coastguard Worker except IndexError: 106*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Unterminated string starting at", 107*cda5da8dSAndroid Build Coastguard Worker s, begin) from None 108*cda5da8dSAndroid Build Coastguard Worker # If not a unicode escape sequence, must be in the lookup table 109*cda5da8dSAndroid Build Coastguard Worker if esc != 'u': 110*cda5da8dSAndroid Build Coastguard Worker try: 111*cda5da8dSAndroid Build Coastguard Worker char = _b[esc] 112*cda5da8dSAndroid Build Coastguard Worker except KeyError: 113*cda5da8dSAndroid Build Coastguard Worker msg = "Invalid \\escape: {0!r}".format(esc) 114*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError(msg, s, end) 115*cda5da8dSAndroid Build Coastguard Worker end += 1 116*cda5da8dSAndroid Build Coastguard Worker else: 117*cda5da8dSAndroid Build Coastguard Worker uni = _decode_uXXXX(s, end) 118*cda5da8dSAndroid Build Coastguard Worker end += 5 119*cda5da8dSAndroid Build Coastguard Worker if 0xd800 <= uni <= 0xdbff and s[end:end + 2] == '\\u': 120*cda5da8dSAndroid Build Coastguard Worker uni2 = _decode_uXXXX(s, end + 1) 121*cda5da8dSAndroid Build Coastguard Worker if 0xdc00 <= uni2 <= 0xdfff: 122*cda5da8dSAndroid Build Coastguard Worker uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) 123*cda5da8dSAndroid Build Coastguard Worker end += 6 124*cda5da8dSAndroid Build Coastguard Worker char = chr(uni) 125*cda5da8dSAndroid Build Coastguard Worker _append(char) 126*cda5da8dSAndroid Build Coastguard Worker return ''.join(chunks), end 127*cda5da8dSAndroid Build Coastguard Worker 128*cda5da8dSAndroid Build Coastguard Worker 129*cda5da8dSAndroid Build Coastguard Worker# Use speedup if available 130*cda5da8dSAndroid Build Coastguard Workerscanstring = c_scanstring or py_scanstring 131*cda5da8dSAndroid Build Coastguard Worker 132*cda5da8dSAndroid Build Coastguard WorkerWHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) 133*cda5da8dSAndroid Build Coastguard WorkerWHITESPACE_STR = ' \t\n\r' 134*cda5da8dSAndroid Build Coastguard Worker 135*cda5da8dSAndroid Build Coastguard Worker 136*cda5da8dSAndroid Build Coastguard Workerdef JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook, 137*cda5da8dSAndroid Build Coastguard Worker memo=None, _w=WHITESPACE.match, _ws=WHITESPACE_STR): 138*cda5da8dSAndroid Build Coastguard Worker s, end = s_and_end 139*cda5da8dSAndroid Build Coastguard Worker pairs = [] 140*cda5da8dSAndroid Build Coastguard Worker pairs_append = pairs.append 141*cda5da8dSAndroid Build Coastguard Worker # Backwards compatibility 142*cda5da8dSAndroid Build Coastguard Worker if memo is None: 143*cda5da8dSAndroid Build Coastguard Worker memo = {} 144*cda5da8dSAndroid Build Coastguard Worker memo_get = memo.setdefault 145*cda5da8dSAndroid Build Coastguard Worker # Use a slice to prevent IndexError from being raised, the following 146*cda5da8dSAndroid Build Coastguard Worker # check will raise a more specific ValueError if the string is empty 147*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 148*cda5da8dSAndroid Build Coastguard Worker # Normally we expect nextchar == '"' 149*cda5da8dSAndroid Build Coastguard Worker if nextchar != '"': 150*cda5da8dSAndroid Build Coastguard Worker if nextchar in _ws: 151*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end).end() 152*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 153*cda5da8dSAndroid Build Coastguard Worker # Trivial empty object 154*cda5da8dSAndroid Build Coastguard Worker if nextchar == '}': 155*cda5da8dSAndroid Build Coastguard Worker if object_pairs_hook is not None: 156*cda5da8dSAndroid Build Coastguard Worker result = object_pairs_hook(pairs) 157*cda5da8dSAndroid Build Coastguard Worker return result, end + 1 158*cda5da8dSAndroid Build Coastguard Worker pairs = {} 159*cda5da8dSAndroid Build Coastguard Worker if object_hook is not None: 160*cda5da8dSAndroid Build Coastguard Worker pairs = object_hook(pairs) 161*cda5da8dSAndroid Build Coastguard Worker return pairs, end + 1 162*cda5da8dSAndroid Build Coastguard Worker elif nextchar != '"': 163*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError( 164*cda5da8dSAndroid Build Coastguard Worker "Expecting property name enclosed in double quotes", s, end) 165*cda5da8dSAndroid Build Coastguard Worker end += 1 166*cda5da8dSAndroid Build Coastguard Worker while True: 167*cda5da8dSAndroid Build Coastguard Worker key, end = scanstring(s, end, strict) 168*cda5da8dSAndroid Build Coastguard Worker key = memo_get(key, key) 169*cda5da8dSAndroid Build Coastguard Worker # To skip some function call overhead we optimize the fast paths where 170*cda5da8dSAndroid Build Coastguard Worker # the JSON key separator is ": " or just ":". 171*cda5da8dSAndroid Build Coastguard Worker if s[end:end + 1] != ':': 172*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end).end() 173*cda5da8dSAndroid Build Coastguard Worker if s[end:end + 1] != ':': 174*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Expecting ':' delimiter", s, end) 175*cda5da8dSAndroid Build Coastguard Worker end += 1 176*cda5da8dSAndroid Build Coastguard Worker 177*cda5da8dSAndroid Build Coastguard Worker try: 178*cda5da8dSAndroid Build Coastguard Worker if s[end] in _ws: 179*cda5da8dSAndroid Build Coastguard Worker end += 1 180*cda5da8dSAndroid Build Coastguard Worker if s[end] in _ws: 181*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end + 1).end() 182*cda5da8dSAndroid Build Coastguard Worker except IndexError: 183*cda5da8dSAndroid Build Coastguard Worker pass 184*cda5da8dSAndroid Build Coastguard Worker 185*cda5da8dSAndroid Build Coastguard Worker try: 186*cda5da8dSAndroid Build Coastguard Worker value, end = scan_once(s, end) 187*cda5da8dSAndroid Build Coastguard Worker except StopIteration as err: 188*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Expecting value", s, err.value) from None 189*cda5da8dSAndroid Build Coastguard Worker pairs_append((key, value)) 190*cda5da8dSAndroid Build Coastguard Worker try: 191*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end] 192*cda5da8dSAndroid Build Coastguard Worker if nextchar in _ws: 193*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end + 1).end() 194*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end] 195*cda5da8dSAndroid Build Coastguard Worker except IndexError: 196*cda5da8dSAndroid Build Coastguard Worker nextchar = '' 197*cda5da8dSAndroid Build Coastguard Worker end += 1 198*cda5da8dSAndroid Build Coastguard Worker 199*cda5da8dSAndroid Build Coastguard Worker if nextchar == '}': 200*cda5da8dSAndroid Build Coastguard Worker break 201*cda5da8dSAndroid Build Coastguard Worker elif nextchar != ',': 202*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Expecting ',' delimiter", s, end - 1) 203*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end).end() 204*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 205*cda5da8dSAndroid Build Coastguard Worker end += 1 206*cda5da8dSAndroid Build Coastguard Worker if nextchar != '"': 207*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError( 208*cda5da8dSAndroid Build Coastguard Worker "Expecting property name enclosed in double quotes", s, end - 1) 209*cda5da8dSAndroid Build Coastguard Worker if object_pairs_hook is not None: 210*cda5da8dSAndroid Build Coastguard Worker result = object_pairs_hook(pairs) 211*cda5da8dSAndroid Build Coastguard Worker return result, end 212*cda5da8dSAndroid Build Coastguard Worker pairs = dict(pairs) 213*cda5da8dSAndroid Build Coastguard Worker if object_hook is not None: 214*cda5da8dSAndroid Build Coastguard Worker pairs = object_hook(pairs) 215*cda5da8dSAndroid Build Coastguard Worker return pairs, end 216*cda5da8dSAndroid Build Coastguard Worker 217*cda5da8dSAndroid Build Coastguard Workerdef JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): 218*cda5da8dSAndroid Build Coastguard Worker s, end = s_and_end 219*cda5da8dSAndroid Build Coastguard Worker values = [] 220*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 221*cda5da8dSAndroid Build Coastguard Worker if nextchar in _ws: 222*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end + 1).end() 223*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 224*cda5da8dSAndroid Build Coastguard Worker # Look-ahead for trivial empty array 225*cda5da8dSAndroid Build Coastguard Worker if nextchar == ']': 226*cda5da8dSAndroid Build Coastguard Worker return values, end + 1 227*cda5da8dSAndroid Build Coastguard Worker _append = values.append 228*cda5da8dSAndroid Build Coastguard Worker while True: 229*cda5da8dSAndroid Build Coastguard Worker try: 230*cda5da8dSAndroid Build Coastguard Worker value, end = scan_once(s, end) 231*cda5da8dSAndroid Build Coastguard Worker except StopIteration as err: 232*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Expecting value", s, err.value) from None 233*cda5da8dSAndroid Build Coastguard Worker _append(value) 234*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 235*cda5da8dSAndroid Build Coastguard Worker if nextchar in _ws: 236*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end + 1).end() 237*cda5da8dSAndroid Build Coastguard Worker nextchar = s[end:end + 1] 238*cda5da8dSAndroid Build Coastguard Worker end += 1 239*cda5da8dSAndroid Build Coastguard Worker if nextchar == ']': 240*cda5da8dSAndroid Build Coastguard Worker break 241*cda5da8dSAndroid Build Coastguard Worker elif nextchar != ',': 242*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Expecting ',' delimiter", s, end - 1) 243*cda5da8dSAndroid Build Coastguard Worker try: 244*cda5da8dSAndroid Build Coastguard Worker if s[end] in _ws: 245*cda5da8dSAndroid Build Coastguard Worker end += 1 246*cda5da8dSAndroid Build Coastguard Worker if s[end] in _ws: 247*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end + 1).end() 248*cda5da8dSAndroid Build Coastguard Worker except IndexError: 249*cda5da8dSAndroid Build Coastguard Worker pass 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker return values, end 252*cda5da8dSAndroid Build Coastguard Worker 253*cda5da8dSAndroid Build Coastguard Worker 254*cda5da8dSAndroid Build Coastguard Workerclass JSONDecoder(object): 255*cda5da8dSAndroid Build Coastguard Worker """Simple JSON <https://json.org> decoder 256*cda5da8dSAndroid Build Coastguard Worker 257*cda5da8dSAndroid Build Coastguard Worker Performs the following translations in decoding by default: 258*cda5da8dSAndroid Build Coastguard Worker 259*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 260*cda5da8dSAndroid Build Coastguard Worker | JSON | Python | 261*cda5da8dSAndroid Build Coastguard Worker +===============+===================+ 262*cda5da8dSAndroid Build Coastguard Worker | object | dict | 263*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 264*cda5da8dSAndroid Build Coastguard Worker | array | list | 265*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 266*cda5da8dSAndroid Build Coastguard Worker | string | str | 267*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 268*cda5da8dSAndroid Build Coastguard Worker | number (int) | int | 269*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 270*cda5da8dSAndroid Build Coastguard Worker | number (real) | float | 271*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 272*cda5da8dSAndroid Build Coastguard Worker | true | True | 273*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 274*cda5da8dSAndroid Build Coastguard Worker | false | False | 275*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 276*cda5da8dSAndroid Build Coastguard Worker | null | None | 277*cda5da8dSAndroid Build Coastguard Worker +---------------+-------------------+ 278*cda5da8dSAndroid Build Coastguard Worker 279*cda5da8dSAndroid Build Coastguard Worker It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as 280*cda5da8dSAndroid Build Coastguard Worker their corresponding ``float`` values, which is outside the JSON spec. 281*cda5da8dSAndroid Build Coastguard Worker 282*cda5da8dSAndroid Build Coastguard Worker """ 283*cda5da8dSAndroid Build Coastguard Worker 284*cda5da8dSAndroid Build Coastguard Worker def __init__(self, *, object_hook=None, parse_float=None, 285*cda5da8dSAndroid Build Coastguard Worker parse_int=None, parse_constant=None, strict=True, 286*cda5da8dSAndroid Build Coastguard Worker object_pairs_hook=None): 287*cda5da8dSAndroid Build Coastguard Worker """``object_hook``, if specified, will be called with the result 288*cda5da8dSAndroid Build Coastguard Worker of every JSON object decoded and its return value will be used in 289*cda5da8dSAndroid Build Coastguard Worker place of the given ``dict``. This can be used to provide custom 290*cda5da8dSAndroid Build Coastguard Worker deserializations (e.g. to support JSON-RPC class hinting). 291*cda5da8dSAndroid Build Coastguard Worker 292*cda5da8dSAndroid Build Coastguard Worker ``object_pairs_hook``, if specified will be called with the result of 293*cda5da8dSAndroid Build Coastguard Worker every JSON object decoded with an ordered list of pairs. The return 294*cda5da8dSAndroid Build Coastguard Worker value of ``object_pairs_hook`` will be used instead of the ``dict``. 295*cda5da8dSAndroid Build Coastguard Worker This feature can be used to implement custom decoders. 296*cda5da8dSAndroid Build Coastguard Worker If ``object_hook`` is also defined, the ``object_pairs_hook`` takes 297*cda5da8dSAndroid Build Coastguard Worker priority. 298*cda5da8dSAndroid Build Coastguard Worker 299*cda5da8dSAndroid Build Coastguard Worker ``parse_float``, if specified, will be called with the string 300*cda5da8dSAndroid Build Coastguard Worker of every JSON float to be decoded. By default this is equivalent to 301*cda5da8dSAndroid Build Coastguard Worker float(num_str). This can be used to use another datatype or parser 302*cda5da8dSAndroid Build Coastguard Worker for JSON floats (e.g. decimal.Decimal). 303*cda5da8dSAndroid Build Coastguard Worker 304*cda5da8dSAndroid Build Coastguard Worker ``parse_int``, if specified, will be called with the string 305*cda5da8dSAndroid Build Coastguard Worker of every JSON int to be decoded. By default this is equivalent to 306*cda5da8dSAndroid Build Coastguard Worker int(num_str). This can be used to use another datatype or parser 307*cda5da8dSAndroid Build Coastguard Worker for JSON integers (e.g. float). 308*cda5da8dSAndroid Build Coastguard Worker 309*cda5da8dSAndroid Build Coastguard Worker ``parse_constant``, if specified, will be called with one of the 310*cda5da8dSAndroid Build Coastguard Worker following strings: -Infinity, Infinity, NaN. 311*cda5da8dSAndroid Build Coastguard Worker This can be used to raise an exception if invalid JSON numbers 312*cda5da8dSAndroid Build Coastguard Worker are encountered. 313*cda5da8dSAndroid Build Coastguard Worker 314*cda5da8dSAndroid Build Coastguard Worker If ``strict`` is false (true is the default), then control 315*cda5da8dSAndroid Build Coastguard Worker characters will be allowed inside strings. Control characters in 316*cda5da8dSAndroid Build Coastguard Worker this context are those with character codes in the 0-31 range, 317*cda5da8dSAndroid Build Coastguard Worker including ``'\\t'`` (tab), ``'\\n'``, ``'\\r'`` and ``'\\0'``. 318*cda5da8dSAndroid Build Coastguard Worker """ 319*cda5da8dSAndroid Build Coastguard Worker self.object_hook = object_hook 320*cda5da8dSAndroid Build Coastguard Worker self.parse_float = parse_float or float 321*cda5da8dSAndroid Build Coastguard Worker self.parse_int = parse_int or int 322*cda5da8dSAndroid Build Coastguard Worker self.parse_constant = parse_constant or _CONSTANTS.__getitem__ 323*cda5da8dSAndroid Build Coastguard Worker self.strict = strict 324*cda5da8dSAndroid Build Coastguard Worker self.object_pairs_hook = object_pairs_hook 325*cda5da8dSAndroid Build Coastguard Worker self.parse_object = JSONObject 326*cda5da8dSAndroid Build Coastguard Worker self.parse_array = JSONArray 327*cda5da8dSAndroid Build Coastguard Worker self.parse_string = scanstring 328*cda5da8dSAndroid Build Coastguard Worker self.memo = {} 329*cda5da8dSAndroid Build Coastguard Worker self.scan_once = scanner.make_scanner(self) 330*cda5da8dSAndroid Build Coastguard Worker 331*cda5da8dSAndroid Build Coastguard Worker 332*cda5da8dSAndroid Build Coastguard Worker def decode(self, s, _w=WHITESPACE.match): 333*cda5da8dSAndroid Build Coastguard Worker """Return the Python representation of ``s`` (a ``str`` instance 334*cda5da8dSAndroid Build Coastguard Worker containing a JSON document). 335*cda5da8dSAndroid Build Coastguard Worker 336*cda5da8dSAndroid Build Coastguard Worker """ 337*cda5da8dSAndroid Build Coastguard Worker obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 338*cda5da8dSAndroid Build Coastguard Worker end = _w(s, end).end() 339*cda5da8dSAndroid Build Coastguard Worker if end != len(s): 340*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Extra data", s, end) 341*cda5da8dSAndroid Build Coastguard Worker return obj 342*cda5da8dSAndroid Build Coastguard Worker 343*cda5da8dSAndroid Build Coastguard Worker def raw_decode(self, s, idx=0): 344*cda5da8dSAndroid Build Coastguard Worker """Decode a JSON document from ``s`` (a ``str`` beginning with 345*cda5da8dSAndroid Build Coastguard Worker a JSON document) and return a 2-tuple of the Python 346*cda5da8dSAndroid Build Coastguard Worker representation and the index in ``s`` where the document ended. 347*cda5da8dSAndroid Build Coastguard Worker 348*cda5da8dSAndroid Build Coastguard Worker This can be used to decode a JSON document from a string that may 349*cda5da8dSAndroid Build Coastguard Worker have extraneous data at the end. 350*cda5da8dSAndroid Build Coastguard Worker 351*cda5da8dSAndroid Build Coastguard Worker """ 352*cda5da8dSAndroid Build Coastguard Worker try: 353*cda5da8dSAndroid Build Coastguard Worker obj, end = self.scan_once(s, idx) 354*cda5da8dSAndroid Build Coastguard Worker except StopIteration as err: 355*cda5da8dSAndroid Build Coastguard Worker raise JSONDecodeError("Expecting value", s, err.value) from None 356*cda5da8dSAndroid Build Coastguard Worker return obj, end 357