1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""Implementation of JSONEncoder
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport re
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry:
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    from _json import encode_basestring_ascii as c_encode_basestring_ascii
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept ImportError:
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    c_encode_basestring_ascii = None
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry:
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    from _json import make_encoder as c_make_encoder
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept ImportError:
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    c_make_encoder = None
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehHAS_UTF8 = re.compile(r'[\x80-\xff]')
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehESCAPE_DCT = {
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '\\': '\\\\',
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '"': '\\"',
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '\b': '\\b',
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '\f': '\\f',
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '\n': '\\n',
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '\r': '\\r',
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    '\t': '\\t',
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh}
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfor i in range(0x20):
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehINFINITY = float('inf')
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehFLOAT_REPR = repr
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef encode_basestring(s):
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """Return a JSON representation of a Python string
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def replace(match):
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return ESCAPE_DCT[match.group(0)]
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    return '"' + ESCAPE.sub(replace, s) + '"'
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef py_encode_basestring_ascii(s):
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """Return an ASCII-only JSON representation of a Python string
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    if isinstance(s, str) and HAS_UTF8.search(s) is not None:
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        s = s.decode('utf-8')
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def replace(match):
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        s = match.group(0)
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return ESCAPE_DCT[s]
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except KeyError:
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            n = ord(s)
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if n < 0x10000:
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return '\\u{0:04x}'.format(n)
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                #return '\\u%04x' % (n,)
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                # surrogate pair
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                n -= 0x10000
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                s1 = 0xd800 | ((n >> 10) & 0x3ff)
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                s2 = 0xdc00 | (n & 0x3ff)
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                #return '\\u%04x\\u%04x' % (s1, s2)
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehencode_basestring_ascii = (
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    c_encode_basestring_ascii or py_encode_basestring_ascii)
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass JSONEncoder(object):
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """Extensible JSON <http://json.org> encoder for Python data structures.
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    Supports the following objects and types by default:
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | Python            | JSON          |
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +===================+===============+
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | dict              | object        |
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | list, tuple       | array         |
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | str, unicode      | string        |
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | int, long, float  | number        |
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | True              | true          |
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | False             | false         |
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    | None              | null          |
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    +-------------------+---------------+
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    To extend this to recognize other objects, subclass and implement a
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ``.default()`` method with another method that returns a serializable
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    object for ``o`` if possible, otherwise it should call the superclass
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    implementation (to raise ``TypeError``).
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    item_separator = ', '
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    key_separator = ': '
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, skipkeys=False, ensure_ascii=True,
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            check_circular=True, allow_nan=True, sort_keys=False,
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            indent=None, separators=None, encoding='utf-8', default=None):
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Constructor for JSONEncoder, with sensible defaults.
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If skipkeys is false, then it is a TypeError to attempt
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        encoding of keys that are not str, int, long, float or None.  If
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        skipkeys is True, such items are simply skipped.
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If *ensure_ascii* is true (the default), all non-ASCII
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        characters in the output are escaped with \uXXXX sequences,
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        and the results are str instances consisting of ASCII
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        characters only.  If ensure_ascii is False, a result may be a
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        unicode instance.  This usually happens if the input contains
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        unicode strings or the *encoding* parameter is used.
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If check_circular is true, then lists, dicts, and custom encoded
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        objects will be checked for circular references during encoding to
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        prevent an infinite recursion (which would cause an OverflowError).
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        Otherwise, no such check takes place.
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If allow_nan is true, then NaN, Infinity, and -Infinity will be
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        encoded as such.  This behavior is not JSON specification compliant,
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        but is consistent with most JavaScript based encoders and decoders.
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        Otherwise, it will be a ValueError to encode such floats.
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If sort_keys is true, then the output of dictionaries will be
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        sorted by key; this is useful for regression tests to ensure
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        that JSON serializations can be compared on a day-to-day basis.
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If indent is a non-negative integer, then JSON array
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elements and object members will be pretty-printed with that
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        indent level.  An indent level of 0 will only insert newlines.
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        None is the most compact representation.  Since the default
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        item separator is ', ',  the output might include trailing
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        whitespace when indent is specified.  You can use
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        separators=(',', ': ') to avoid this.
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If specified, separators should be a (item_separator, key_separator)
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        tuple.  The default is (', ', ': ').  To get the most compact JSON
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        representation you should specify (',', ':') to eliminate whitespace.
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If specified, default is a function that gets called for objects
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        that can't otherwise be serialized.  It should return a JSON encodable
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        version of the object or raise a ``TypeError``.
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        If encoding is not None, then all input strings will be
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        transformed into unicode using that encoding prior to JSON-encoding.
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        The default is UTF-8.
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.skipkeys = skipkeys
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.ensure_ascii = ensure_ascii
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.check_circular = check_circular
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.allow_nan = allow_nan
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.sort_keys = sort_keys
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.indent = indent
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if separators is not None:
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.item_separator, self.key_separator = separators
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if default is not None:
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.default = default
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.encoding = encoding
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def default(self, o):
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Implement this method in a subclass such that it returns
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        a serializable object for ``o``, or calls the base implementation
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        (to raise a ``TypeError``).
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        For example, to support arbitrary iterators, you could
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        implement default like this::
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            def default(self, o):
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                try:
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    iterable = iter(o)
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                except TypeError:
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    pass
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                else:
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    return list(iterable)
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                # Let the base class default method raise the TypeError
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return JSONEncoder.default(self, o)
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        raise TypeError(repr(o) + " is not JSON serializable")
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def encode(self, o):
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Return a JSON string representation of a Python data structure.
188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        '{"foo": ["bar", "baz"]}'
191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # This is for extremely simple cases and benchmarks.
194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(o, basestring):
195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if isinstance(o, str):
196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                _encoding = self.encoding
197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if (_encoding is not None
198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        and not (_encoding == 'utf-8')):
199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    o = o.decode(_encoding)
200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if self.ensure_ascii:
201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return encode_basestring_ascii(o)
202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return encode_basestring(o)
204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # This doesn't pass the iterator directly to ''.join() because the
205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # exceptions aren't as detailed.  The list call should be roughly
206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # equivalent to the PySequence_Fast that ''.join() would do.
207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        chunks = self.iterencode(o, _one_shot=True)
208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if not isinstance(chunks, (list, tuple)):
209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            chunks = list(chunks)
210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return ''.join(chunks)
211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def iterencode(self, o, _one_shot=False):
213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Encode the given object and yield each string
214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        representation as available.
215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        For example::
217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for chunk in JSONEncoder().iterencode(bigobject):
219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                mysocket.write(chunk)
220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.check_circular:
223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            markers = {}
224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            markers = None
226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.ensure_ascii:
227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _encoder = encode_basestring_ascii
228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _encoder = encode_basestring
230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.encoding != 'utf-8':
231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if isinstance(o, str):
233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    o = o.decode(_encoding)
234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return _orig_encoder(o)
235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        def floatstr(o, allow_nan=self.allow_nan,
237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY):
238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # Check for specials.  Note that this type of test is processor
239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # and/or platform-specific, so do tests which don't depend on the
240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # internals.
241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if o != o:
243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                text = 'NaN'
244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif o == _inf:
245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                text = 'Infinity'
246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif o == _neginf:
247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                text = '-Infinity'
248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return _repr(o)
250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if not allow_nan:
252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                raise ValueError(
253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    "Out of range float values are not JSON compliant: " +
254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    repr(o))
255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return text
257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if (_one_shot and c_make_encoder is not None
260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                and self.indent is None and not self.sort_keys):
261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _iterencode = c_make_encoder(
262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                markers, self.default, _encoder, self.indent,
263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.key_separator, self.item_separator, self.sort_keys,
264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.skipkeys, self.allow_nan)
265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _iterencode = _make_iterencode(
267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                markers, self.default, _encoder, self.indent, floatstr,
268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.key_separator, self.item_separator, self.sort_keys,
269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.skipkeys, _one_shot)
270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return _iterencode(o, 0)
271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ## HACK: hand-optimized bytecode; turn globals into locals
275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ValueError=ValueError,
276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        basestring=basestring,
277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        dict=dict,
278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        float=float,
279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        id=id,
280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        int=int,
281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        isinstance=isinstance,
282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        list=list,
283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        long=long,
284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        str=str,
285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        tuple=tuple,
286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ):
287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def _iterencode_list(lst, _current_indent_level):
289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if not lst:
290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield '[]'
291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return
292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if markers is not None:
293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            markerid = id(lst)
294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if markerid in markers:
295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                raise ValueError("Circular reference detected")
296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            markers[markerid] = lst
297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        buf = '['
298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if _indent is not None:
299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _current_indent_level += 1
300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            separator = _item_separator + newline_indent
302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            buf += newline_indent
303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            newline_indent = None
305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            separator = _item_separator
306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        first = True
307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for value in lst:
308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if first:
309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                first = False
310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                buf = separator
312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if isinstance(value, basestring):
313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf + _encoder(value)
314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif value is None:
315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf + 'null'
316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif value is True:
317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf + 'true'
318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif value is False:
319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf + 'false'
320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif isinstance(value, (int, long)):
321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf + str(value)
322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif isinstance(value, float):
323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf + _floatstr(value)
324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield buf
326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if isinstance(value, (list, tuple)):
327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    chunks = _iterencode_list(value, _current_indent_level)
328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                elif isinstance(value, dict):
329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    chunks = _iterencode_dict(value, _current_indent_level)
330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                else:
331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    chunks = _iterencode(value, _current_indent_level)
332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                for chunk in chunks:
333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    yield chunk
334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if newline_indent is not None:
335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _current_indent_level -= 1
336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield '\n' + (' ' * (_indent * _current_indent_level))
337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        yield ']'
338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if markers is not None:
339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            del markers[markerid]
340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def _iterencode_dict(dct, _current_indent_level):
342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if not dct:
343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield '{}'
344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return
345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if markers is not None:
346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            markerid = id(dct)
347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if markerid in markers:
348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                raise ValueError("Circular reference detected")
349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            markers[markerid] = dct
350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        yield '{'
351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if _indent is not None:
352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _current_indent_level += 1
353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            item_separator = _item_separator + newline_indent
355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield newline_indent
356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            newline_indent = None
358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            item_separator = _item_separator
359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        first = True
360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if _sort_keys:
361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            items = sorted(dct.items(), key=lambda kv: kv[0])
362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            items = dct.iteritems()
364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for key, value in items:
365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if isinstance(key, basestring):
366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                pass
367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # JavaScript is weakly typed for these, so it makes sense to
368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # also allow them.  Many encoders seem to do something like this.
369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif isinstance(key, float):
370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                key = _floatstr(key)
371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif key is True:
372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                key = 'true'
373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif key is False:
374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                key = 'false'
375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif key is None:
376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                key = 'null'
377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif isinstance(key, (int, long)):
378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                key = str(key)
379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif _skipkeys:
380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                continue
381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                raise TypeError("key " + repr(key) + " is not a string")
383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if first:
384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                first = False
385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield item_separator
387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield _encoder(key)
388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield _key_separator
389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if isinstance(value, basestring):
390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield _encoder(value)
391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif value is None:
392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield 'null'
393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif value is True:
394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield 'true'
395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif value is False:
396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield 'false'
397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif isinstance(value, (int, long)):
398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield str(value)
399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif isinstance(value, float):
400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield _floatstr(value)
401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if isinstance(value, (list, tuple)):
403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    chunks = _iterencode_list(value, _current_indent_level)
404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                elif isinstance(value, dict):
405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    chunks = _iterencode_dict(value, _current_indent_level)
406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                else:
407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    chunks = _iterencode(value, _current_indent_level)
408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                for chunk in chunks:
409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    yield chunk
410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if newline_indent is not None:
411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _current_indent_level -= 1
412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield '\n' + (' ' * (_indent * _current_indent_level))
413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        yield '}'
414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if markers is not None:
415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            del markers[markerid]
416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def _iterencode(o, _current_indent_level):
418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(o, basestring):
419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield _encoder(o)
420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif o is None:
421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield 'null'
422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif o is True:
423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield 'true'
424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif o is False:
425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield 'false'
426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(o, (int, long)):
427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield str(o)
428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(o, float):
429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            yield _floatstr(o)
430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(o, (list, tuple)):
431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for chunk in _iterencode_list(o, _current_indent_level):
432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield chunk
433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(o, dict):
434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for chunk in _iterencode_dict(o, _current_indent_level):
435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield chunk
436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if markers is not None:
438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                markerid = id(o)
439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if markerid in markers:
440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    raise ValueError("Circular reference detected")
441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                markers[markerid] = o
442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            o = _default(o)
443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for chunk in _iterencode(o, _current_indent_level):
444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                yield chunk
445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if markers is not None:
446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                del markers[markerid]
447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    return _iterencode
449