def parse_array(self, s_and_end, root, working, _w=WHITESPACE.match, _ws=WHITESPACE_STR): s, end = s_and_end nextchar = s[end:end + 1] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end:end + 1] # Look-ahead for trivial empty array if nextchar == ']': return working, end + 1 _append = working.append while True: try: nextchar = s[end] except IndexError: raise ValueError(errmsg("Expecting object", s, end)) if nextchar == '{': nextitem = {} elif nextchar == '[': nextitem = [] else: nextitem = None _append(nextitem) try: value, end = self.scan_once(s, end, root, nextitem) except StopIteration: raise ValueError(errmsg("Expecting object", s, end)) if value is not nextitem: del working[-1] _append(value) nextchar = s[end:end + 1] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end:end + 1] end += 1 if nextchar == ']': break elif nextchar != ',': raise ValueError(errmsg("Expecting ',' delimiter", s, end)) try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() except IndexError: pass return working, end
def raw_decode(self, s, idx=0): """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning with a JSON document) and return a 2-tuple of the Python representation and the index in ``s`` where the document ended. This can be used to decode a JSON document from a string that may have extraneous data at the end. """ try: nextchar = s[idx] except IndexError: raise ValueError(errmsg("Expecting object", s, idx)) if nextchar == '{': root = {} elif nextchar == '[': root = [] else: root = None try: obj, end = self.scan_once(s, idx, root, root) except StopIteration: raise ValueError("No JSON object could be decoded") return obj, end
def _JSONArray(s_and_end, scan_once, _w=decoder.WHITESPACE.match, _ws=decoder.WHITESPACE_STR): s, end = s_and_end values = [] nextchar = s[end:end + 1] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end:end + 1] # Look-ahead for trivial empty array if nextchar == ']': return values, end + 1 _append = values.append while True: m = ELLIPSIS.match(s[end:]) if m is not None: count = 1 if m.group(1) is None else int(m.group(1)) values.extend((Ellipsis, ) * count) end += m.end() else: try: value, end = scan_once(s, end) except StopIteration: raise ValueError(decoder.errmsg("Expecting object", s, end)) _append(value) nextchar = s[end:end + 1] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end:end + 1] end += 1 if nextchar == ']': break elif nextchar != ',': raise ValueError(decoder.errmsg("Expecting ',' delimiter", s, end)) try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() except IndexError: pass return values, end
def decode(self, s, _w=WHITESPACE.match): """Return the Python representation of ``s`` (a ``str`` or ``unicode`` instance containing a JSON document) """ obj, end = self.raw_decode(s, idx=_w(s, 0).end()) end = _w(s, end).end() if end != len(s): raise ValueError(errmsg("Extra data", s, end, len(s))) return obj
def _JSONArray(s_and_end, scan_once, _w=decoder.WHITESPACE.match, _ws=decoder.WHITESPACE_STR): s, end = s_and_end values = [] nextchar = s[end:end + 1] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end:end + 1] # Look-ahead for trivial empty array if nextchar == ']': return values, end + 1 _append = values.append while True: m = ELLIPSIS.match(s[end:]) if m is not None: count = 1 if m.group(1) is None else int(m.group(1)) values.extend((Ellipsis,) * count) end += m.end() else: try: value, end = scan_once(s, end) except StopIteration: raise ValueError(decoder.errmsg("Expecting object", s, end)) _append(value) nextchar = s[end:end + 1] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end:end + 1] end += 1 if nextchar == ']': break elif nextchar != ',': raise ValueError(decoder.errmsg("Expecting ',' delimiter", s, end)) try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() except IndexError: pass return values, end
def JSONObject(match, context, _w=decoder.WHITESPACE.match): pairs = OrderedDict(); # Change to an ordered dict s = match.string end = _w(s, match.end()).end() nextchar = s[end:end + 1] # Trivial empty object if nextchar == '}': return pairs, end + 1 if nextchar != '"': raise ValueError(decoder.errmsg("Expecting property name", s, end)) end += 1 encoding = getattr(context, 'encoding', None) strict = getattr(context, 'strict', True) iterscan = JSONScanner.iterscan while True: key, end = decoder.scanstring(s, end, encoding, strict) end = _w(s, end).end() if s[end:end + 1] != ':': raise ValueError(decoder.errmsg("Expecting : delimiter", s, end)) end = _w(s, end + 1).end() try: value, end = iterscan(s, idx=end, context=context).next() except StopIteration: raise ValueError(decoder.errmsg("Expecting object", s, end)) pairs[key] = value end = _w(s, end).end() nextchar = s[end:end + 1] end += 1 if nextchar == '}': break if nextchar != ',': raise ValueError(decoder.errmsg("Expecting , delimiter", s, end - 1)) end = _w(s, end).end() nextchar = s[end:end + 1] end += 1 if nextchar != '"': raise ValueError(decoder.errmsg("Expecting property name", s, end - 1)) object_hook = getattr(context, 'object_hook', None) if object_hook is not None: pairs = object_hook(pairs) return pairs, end
def _JSONObject(s_and_end, *args): # The function signature of json.scanner.JSONObject() changed # between python versions 2.7 and 3. The following is an ugly # shim to compensate. _w = decoder.WHITESPACE.match _ws = decoder.WHITESPACE_STR if isinstance(args[0], bool): (strict, scan_once, object_hook, object_pairs_hook, memo) = args else: (encoding, strict, scan_once, object_hook, object_pairs_hook) = args def check_ellipsis(end): if s[end:end + 3] == '...': pairs_append((Ellipsis, True)) end += 3 if s[end] == ',': end += 1 return end def consume_whitespace(end): try: nextchar = s[end] if nextchar in _ws: end += 1 nextchar = s[end] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end] except IndexError: nextchar = '' return nextchar, end s, end = s_and_end pairs = [] pairs_append = pairs.append # Use a slice to prevent IndexError from being raised, the following # check will raise a more specific ValueError if the string is empty nextchar = s[end:end + 1] # Normally we expect nextchar == '"' if nextchar != '"': if nextchar in _ws: end = _w(s, end).end() nextchar = s[end:end + 1] end = check_ellipsis(end) nextchar = s[end:end + 1] # Trivial empty object if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) return result, end + 1 pairs = dict(pairs) if object_hook is not None: pairs = object_hook(pairs) return pairs, end + 1 elif nextchar != '"': raise ValueError( decoder.errmsg( "Expecting property name enclosed in double quotes", s, end)) end += 1 while True: key, end = decoder.py_scanstring(s, end, strict=strict) # To skip some function call overhead we optimize the fast paths where # the JSON key separator is ": " or just ":". if s[end:end + 1] != ':': end = _w(s, end).end() if s[end:end + 1] != ':': raise ValueError( decoder.errmsg("Expecting ':' delimiter", s, end)) end += 1 try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() except IndexError: pass try: value, end = scan_once(s, end) except StopIteration: raise ValueError(decoder.errmsg("Expecting object", s, end)) pairs_append((key, value)) try: nextchar = s[end] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end] except IndexError: nextchar = '' end += 1 if nextchar == '}': break elif nextchar != ',': raise ValueError( decoder.errmsg("Expecting ',' delimiter", s, end - 1)) nextchar, end = consume_whitespace(end) end = check_ellipsis(end) nextchar, end = consume_whitespace(end) end += 1 if nextchar == '}': break if nextchar != '"': raise ValueError( decoder.errmsg( "Expecting property name enclosed in double quotes", s, end - 1)) if object_pairs_hook is not None: result = object_pairs_hook(pairs) return result, end pairs = dict(pairs) if object_hook is not None: pairs = object_hook(pairs) return pairs, end
def _JSONObject(s_and_end, *args): # The function signature of json.scanner.JSONObject() changed # between python versions 2.7 and 3. The following is an ugly # shim to compensate. _w = decoder.WHITESPACE.match _ws = decoder.WHITESPACE_STR if isinstance(args[0], bool): (strict, scan_once, object_hook, object_pairs_hook, memo) = args else: (encoding, strict, scan_once, object_hook, object_pairs_hook) = args def check_ellipsis(end): if s[end:end+3] == '...': pairs_append((Ellipsis, True)) end += 3 if s[end] == ',': end += 1 return end def consume_whitespace(end): try: nextchar = s[end] if nextchar in _ws: end += 1 nextchar = s[end] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end] except IndexError: nextchar = '' return nextchar, end s, end = s_and_end pairs = [] pairs_append = pairs.append # Use a slice to prevent IndexError from being raised, the following # check will raise a more specific ValueError if the string is empty nextchar = s[end:end + 1] # Normally we expect nextchar == '"' if nextchar != '"': if nextchar in _ws: end = _w(s, end).end() nextchar = s[end:end + 1] end = check_ellipsis(end) nextchar = s[end:end + 1] # Trivial empty object if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) return result, end + 1 pairs = dict(pairs) if object_hook is not None: pairs = object_hook(pairs) return pairs, end + 1 elif nextchar != '"': raise ValueError(decoder.errmsg( "Expecting property name enclosed in double quotes", s, end)) end += 1 while True: key, end = decoder.py_scanstring(s, end, strict=strict) # To skip some function call overhead we optimize the fast paths where # the JSON key separator is ": " or just ":". if s[end:end + 1] != ':': end = _w(s, end).end() if s[end:end + 1] != ':': raise ValueError(decoder.errmsg("Expecting ':' delimiter", s, end)) end += 1 try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() except IndexError: pass try: value, end = scan_once(s, end) except StopIteration: raise ValueError(decoder.errmsg("Expecting object", s, end)) pairs_append((key, value)) try: nextchar = s[end] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end] except IndexError: nextchar = '' end += 1 if nextchar == '}': break elif nextchar != ',': raise ValueError(decoder.errmsg("Expecting ',' delimiter", s, end - 1)) nextchar, end = consume_whitespace(end) end = check_ellipsis(end) nextchar, end = consume_whitespace(end) end += 1 if nextchar == '}': break if nextchar != '"': raise ValueError(decoder.errmsg( "Expecting property name enclosed in double quotes", s, end - 1)) if object_pairs_hook is not None: result = object_pairs_hook(pairs) return result, end pairs = dict(pairs) if object_hook is not None: pairs = object_hook(pairs) return pairs, end
def parse_object(self, s_and_end, root, working, _w=WHITESPACE.match, _ws=WHITESPACE_STR): s, end = s_and_end pairs = [] pairs_append = pairs.append # Use a slice to prevent IndexError from being raised, the following # check will raise a more specific ValueError if the string is empty nextchar = s[end:end + 1] # Normally we expect nextchar == '"' if nextchar != '"': if nextchar in _ws: end = _w(s, end).end() nextchar = s[end:end + 1] # Trivial empty object if nextchar == '}': if self.object_dict_hook is not None: result = self.object_dict_hook(working) return result, end + 1 if self.object_hook is not None: working = self.object_hook(working) return working, end + 1 elif nextchar != '"': raise ValueError(errmsg( "Expecting property name enclosed in double quotes", s, end)) end += 1 while True: key, end = self.parse_string(s, end) # To skip some function call overhead we optimize the fast paths where # the JSON key separator is ": " or just ":". if s[end:end + 1] != ':': end = _w(s, end).end() if s[end:end + 1] != ':': raise ValueError(errmsg("Expecting ':' delimiter", s, end)) end += 1 try: if s[end] in _ws: end += 1 if s[end] in _ws: end = _w(s, end + 1).end() except IndexError: pass try: nextchar = s[end] except IndexError: raise ValueError(errmsg("Expecting object", s, end)) if nextchar == '{': nextitem = {} elif nextchar == '[': nextitem = [] else: nextitem = None working[key] = nextitem try: value, end = self.scan_once(s, end, root, nextitem) except StopIteration: raise ValueError(errmsg("Expecting object", s, end)) # pairs_append((key, value)) working[key] = value try: nextchar = s[end] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end] except IndexError: nextchar = '' end += 1 if nextchar == '}': break elif nextchar != ',': raise ValueError(errmsg("Expecting ',' delimiter", s, end - 1)) try: nextchar = s[end] if nextchar in _ws: end += 1 nextchar = s[end] if nextchar in _ws: end = _w(s, end + 1).end() nextchar = s[end] except IndexError: nextchar = '' end += 1 if nextchar != '"': raise ValueError(errmsg( "Expecting property name enclosed in double quotes", s, end - 1)) if self.object_pairs_hook is not None: result = self.object_dict_hook(dict) return result, end if self.object_hook is not None: working = self.object_hook(working) return working, end