0001"""
0002Implementation of JSONEncoder
0003"""
0004import re
0005
0006ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]')
0007ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])')
0008ESCAPE_DCT = {
0009    # escape all forward slashes to prevent </script> attack
0010    '/': '\\/',
0011    '\\': '\\\\',
0012    '"': '\\"',
0013    '\b': '\\b',
0014    '\f': '\\f',
0015    '\n': '\\n',
0016    '\r': '\\r',
0017    '\t': '\\t',
0018}
0019for i in range(0x20):
0020    ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
0021
0022# assume this produces an infinity on all machines (probably not guaranteed)
0023INFINITY = float('1e66666')
0024
0025def floatstr(o, allow_nan=True):
0026    # Check for specials.  Note that this type of test is processor- and/or
0027    # platform-specific, so do tests which don't depend on the internals.
0028
0029    if o != o:
0030        text = 'NaN'
0031    elif o == INFINITY:
0032        text = 'Infinity'
0033    elif o == -INFINITY:
0034        text = '-Infinity'
0035    else:
0036        return str(o)
0037
0038    if not allow_nan:
0039        raise ValueError("Out of range float values are not JSON compliant: %r"
0040            % (o,))
0041
0042    return text
0043
0044
0045def encode_basestring(s):
0046    """
0047    Return a JSON representation of a Python string
0048    """
0049    def replace(match):
0050        return ESCAPE_DCT[match.group(0)]
0051    return '"' + ESCAPE.sub(replace, s) + '"'
0052
0053def encode_basestring_ascii(s):
0054    def replace(match):
0055        s = match.group(0)
0056        try:
0057            return ESCAPE_DCT[s]
0058        except KeyError:
0059            return '\\u%04x' % (ord(s),)
0060    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
0061
0062
0063class JSONEncoder(object):
0064    """
0065    Extensible JSON <http://json.org> encoder for Python data structures.
0066
0067    Supports the following objects and types by default:
0068    
0069    +-------------------+---------------+
0070    | Python            | JSON          |
0071    +===================+===============+
0072    | dict              | object        |
0073    +-------------------+---------------+
0074    | list, tuple       | array         |
0075    +-------------------+---------------+
0076    | str, unicode      | string        |
0077    +-------------------+---------------+
0078    | int, long, float  | number        |
0079    +-------------------+---------------+
0080    | True              | true          |
0081    +-------------------+---------------+
0082    | False             | false         |
0083    +-------------------+---------------+
0084    | None              | null          |
0085    +-------------------+---------------+
0086
0087    To extend this to recognize other objects, subclass and implement a
0088    ``.default()`` method with another method that returns a serializable
0089    object for ``o`` if possible, otherwise it should call the superclass
0090    implementation (to raise ``TypeError``).
0091    """
0092    __all__ = ['__init__', 'default', 'encode', 'iterencode']
0093    item_separator = ', '
0094    key_separator = ': '
0095    def __init__(self, skipkeys=False, ensure_ascii=True,
0096            check_circular=True, allow_nan=True, sort_keys=False,
0097            indent=None, separators=None):
0098        """
0099        Constructor for JSONEncoder, with sensible defaults.
0100
0101        If skipkeys is False, then it is a TypeError to attempt
0102        encoding of keys that are not str, int, long, float or None.  If
0103        skipkeys is True, such items are simply skipped.
0104
0105        If ensure_ascii is True, the output is guaranteed to be str
0106        objects with all incoming unicode characters escaped.  If
0107        ensure_ascii is false, the output will be unicode object.
0108
0109        If check_circular is True, then lists, dicts, and custom encoded
0110        objects will be checked for circular references during encoding to
0111        prevent an infinite recursion (which would cause an OverflowError).
0112        Otherwise, no such check takes place.
0113
0114        If allow_nan is True, then NaN, Infinity, and -Infinity will be
0115        encoded as such.  This behavior is not JSON specification compliant,
0116        but is consistent with most JavaScript based encoders and decoders.
0117        Otherwise, it will be a ValueError to encode such floats.
0118
0119        If sort_keys is True, then the output of dictionaries will be
0120        sorted by key; this is useful for regression tests to ensure
0121        that JSON serializations can be compared on a day-to-day basis.
0122
0123        If indent is a non-negative integer, then JSON array
0124        elements and object members will be pretty-printed with that
0125        indent level.  An indent level of 0 will only insert newlines.
0126        None is the most compact representation.
0127
0128        If specified, separators should be a (item_separator, key_separator)
0129        tuple. The default is (', ', ': '). To get the most compact JSON
0130        representation you should specify (',', ':') to eliminate whitespace.
0131        """
0132
0133        self.skipkeys = skipkeys
0134        self.ensure_ascii = ensure_ascii
0135        self.check_circular = check_circular
0136        self.allow_nan = allow_nan
0137        self.sort_keys = sort_keys
0138        self.indent = indent
0139        self.current_indent_level = 0
0140        if separators is not None:
0141            self.item_separator, self.key_separator = separators
0142
0143    def _newline_indent(self):
0144        return '\n' + (' ' * (self.indent * self.current_indent_level))
0145
0146    def _iterencode_list(self, lst, markers=None):
0147        if not lst:
0148            yield '[]'
0149            return
0150        if markers is not None:
0151            markerid = id(lst)
0152            if markerid in markers:
0153                raise ValueError("Circular reference detected")
0154            markers[markerid] = lst
0155        yield '['
0156        if self.indent is not None:
0157            self.current_indent_level += 1
0158            newline_indent = self._newline_indent()
0159            separator = self.item_separator + newline_indent
0160            yield newline_indent
0161        else:
0162            newline_indent = None
0163            separator = self.item_separator
0164        first = True
0165        for value in lst:
0166            if first:
0167                first = False
0168            else:
0169                yield separator
0170            for chunk in self._iterencode(value, markers):
0171                yield chunk
0172        if newline_indent is not None:
0173            self.current_indent_level -= 1
0174            yield self._newline_indent()
0175        yield ']'
0176        if markers is not None:
0177            del markers[markerid]
0178
0179    def _iterencode_dict(self, dct, markers=None):
0180        if not dct:
0181            yield '{}'
0182            return
0183        if markers is not None:
0184            markerid = id(dct)
0185            if markerid in markers:
0186                raise ValueError("Circular reference detected")
0187            markers[markerid] = dct
0188        yield '{'
0189        key_separator = self.key_separator
0190        if self.indent is not None:
0191            self.current_indent_level += 1
0192            newline_indent = self._newline_indent()
0193            item_separator = self.item_separator + newline_indent
0194            yield newline_indent
0195        else:
0196            newline_indent = None
0197            item_separator = self.item_separator
0198        first = True
0199        if self.ensure_ascii:
0200            encoder = encode_basestring_ascii
0201        else:
0202            encoder = encode_basestring
0203        allow_nan = self.allow_nan
0204        if self.sort_keys:
0205            keys = dct.keys()
0206            keys.sort()
0207            items = [(k, dct[k]) for k in keys]
0208        else:
0209            items = dct.iteritems()
0210        for key, value in items:
0211            if isinstance(key, basestring):
0212                pass
0213            # JavaScript is weakly typed for these, so it makes sense to
0214            # also allow them.  Many encoders seem to do something like this.
0215            elif isinstance(key, float):
0216                key = floatstr(key, allow_nan)
0217            elif isinstance(key, (int, long)):
0218                key = str(key)
0219            elif key is True:
0220                key = 'true'
0221            elif key is False:
0222                key = 'false'
0223            elif key is None:
0224                key = 'null'
0225            elif self.skipkeys:
0226                continue
0227            else:
0228                raise TypeError("key %r is not a string" % (key,))
0229            if first:
0230                first = False
0231            else:
0232                yield item_separator
0233            yield encoder(key)
0234            yield key_separator
0235            for chunk in self._iterencode(value, markers):
0236                yield chunk
0237        if newline_indent is not None:
0238            self.current_indent_level -= 1
0239            yield self._newline_indent()
0240        yield '}'
0241        if markers is not None:
0242            del markers[markerid]
0243
0244    def _iterencode(self, o, markers=None):
0245        if isinstance(o, basestring):
0246            if self.ensure_ascii:
0247                encoder = encode_basestring_ascii
0248            else:
0249                encoder = encode_basestring
0250            yield encoder(o)
0251        elif o is None:
0252            yield 'null'
0253        elif o is True:
0254            yield 'true'
0255        elif o is False:
0256            yield 'false'
0257        elif isinstance(o, (int, long)):
0258            yield str(o)
0259        elif isinstance(o, float):
0260            yield floatstr(o, self.allow_nan)
0261        elif isinstance(o, (list, tuple)):
0262            for chunk in self._iterencode_list(o, markers):
0263                yield chunk
0264        elif isinstance(o, dict):
0265            for chunk in self._iterencode_dict(o, markers):
0266                yield chunk
0267        else:
0268            if markers is not None:
0269                markerid = id(o)
0270                if markerid in markers:
0271                    raise ValueError("Circular reference detected")
0272                markers[markerid] = o
0273            for chunk in self._iterencode_default(o, markers):
0274                yield chunk
0275            if markers is not None:
0276                del markers[markerid]
0277
0278    def _iterencode_default(self, o, markers=None):
0279        newobj = self.default(o)
0280        return self._iterencode(newobj, markers)
0281
0282    def default(self, o):
0283        """
0284        Implement this method in a subclass such that it returns
0285        a serializable object for ``o``, or calls the base implementation
0286        (to raise a ``TypeError``).
0287
0288        For example, to support arbitrary iterators, you could
0289        implement default like this::
0290            
0291            def default(self, o):
0292                try:
0293                    iterable = iter(o)
0294                except TypeError:
0295                    pass
0296                else:
0297                    return list(iterable)
0298                return JSONEncoder.default(self, o)
0299        """
0300        raise TypeError("%r is not JSON serializable" % (o,))
0301
0302    def encode(self, o):
0303        """
0304        Return a JSON string representation of a Python data structure.
0305
0306        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
0307        '{"foo":["bar", "baz"]}'
0308        """
0309        # This doesn't pass the iterator directly to ''.join() because it
0310        # sucks at reporting exceptions.  It's going to do this internally
0311        # anyway because it uses PySequence_Fast or similar.
0312        chunks = list(self.iterencode(o))
0313        return ''.join(chunks)
0314
0315    def iterencode(self, o):
0316        """
0317        Encode the given object and yield each string
0318        representation as available.
0319        
0320        For example::
0321            
0322            for chunk in JSONEncoder().iterencode(bigobject):
0323                mysocket.write(chunk)
0324        """
0325        if self.check_circular:
0326            markers = {}
0327        else:
0328            markers = None
0329        return self._iterencode(o, markers)
0330
0331__all__ = ['JSONEncoder']