Example #1
0
    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
Example #2
0
    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
Example #3
0
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
Example #4
0
    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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
    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