1"""Implementation of JSONEncoder
2"""
3from __future__ import absolute_import
4import re
5from operator import itemgetter
6# Do not import Decimal directly to avoid reload issues
7import decimal
8import sys
9from .compat import binary_type, text_type, string_types, integer_types, PY3
10
11# PEP 678 add_note() is available on Python 3.11+
12_HAS_ADD_NOTE = sys.version_info >= (3, 11)
13
14def _import_speedups():
15 try:
16 from . import _speedups
17 return (_speedups.encode_basestring_ascii,
18 _speedups.encode_basestring,
19 _speedups.make_encoder)
20 except ImportError:
21 return None, None, None
22c_encode_basestring_ascii, c_encode_basestring, c_make_encoder = (
23 _import_speedups())
24
25from .decoder import PosInf
26from .raw_json import RawJSON
27
28ESCAPE = re.compile(r'[\x00-\x1f\\"]')
29ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
30HAS_UTF8 = re.compile(r'[\x80-\xff]')
31ESCAPE_DCT = {
32 '\\': '\\\\',
33 '"': '\\"',
34 '\b': '\\b',
35 '\f': '\\f',
36 '\n': '\\n',
37 '\r': '\\r',
38 '\t': '\\t',
39}
40for i in range(0x20):
41 ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
42del i
43
44FLOAT_REPR = repr
45
46_NAN = float('nan')
47_INFINITY = float('inf')
48
49
50def _encode_decimal(d, _floatstr):
51 """Return the JSON representation of a ``Decimal``.
52
53 Finite Decimals are stringified as-is, preserving precision and trailing
54 zeros. Non-finite Decimals (``NaN``, ``sNaN``, ``Infinity``) are routed
55 through the same ``allow_nan``/``ignore_nan`` handling as floats so they
56 never emit invalid JSON (see #149).
57
58 ``str(Decimal)`` yields a leading ``-`` sign at most (never ``+``); a
59 finite value's first significant character is always a digit, while a
60 non-finite value's is a letter (``N``, ``s`` or ``I``). So a single
61 ``str()`` plus a one/two character check distinguishes the two.
62 """
63 s = str(d)
64 c0 = s[:1]
65 c = s[1:2] if c0 == '-' else c0
66 if '0' <= c <= '9':
67 # First significant character is a digit: finite Decimal.
68 return s
69 # Non-finite Decimal. ``N``/``s`` -> NaN (float(Decimal('sNaN')) raises,
70 # so map both quiet and signaling NaN to a plain NaN); ``I`` -> Infinity.
71 if c == 'I':
72 return _floatstr(-_INFINITY if c0 == '-' else _INFINITY)
73 return _floatstr(_NAN)
74
75# dict-like types that should be encoded as JSON objects.
76# frozendict is a builtin added in CPython 3.15 (PEP 814).
77if sys.version_info >= (3, 15):
78 _dict_types = (dict, frozendict)
79else:
80 _dict_types = dict
81
82def py_encode_basestring(s, _PY3=PY3, _q=u'"'):
83 """Return a JSON representation of a Python string
84
85 """
86 if _PY3:
87 if isinstance(s, bytes):
88 s = str(s, 'utf-8')
89 elif type(s) is not str:
90 # convert an str subclass instance to exact str
91 # raise a TypeError otherwise
92 s = str.__str__(s)
93 else:
94 if isinstance(s, str) and HAS_UTF8.search(s) is not None:
95 s = unicode(s, 'utf-8')
96 elif type(s) not in (str, unicode):
97 # convert an str subclass instance to exact str
98 # convert a unicode subclass instance to exact unicode
99 # raise a TypeError otherwise
100 if isinstance(s, str):
101 s = str.__str__(s)
102 else:
103 s = unicode.__getnewargs__(s)[0]
104 def replace(match):
105 return ESCAPE_DCT[match.group(0)]
106 return _q + ESCAPE.sub(replace, s) + _q
107
108
109def py_encode_basestring_ascii(s, _PY3=PY3):
110 """Return an ASCII-only JSON representation of a Python string
111
112 """
113 if _PY3:
114 if isinstance(s, bytes):
115 s = str(s, 'utf-8')
116 elif type(s) is not str:
117 # convert an str subclass instance to exact str
118 # raise a TypeError otherwise
119 s = str.__str__(s)
120 else:
121 if isinstance(s, str) and HAS_UTF8.search(s) is not None:
122 s = unicode(s, 'utf-8')
123 elif type(s) not in (str, unicode):
124 # convert an str subclass instance to exact str
125 # convert a unicode subclass instance to exact unicode
126 # raise a TypeError otherwise
127 if isinstance(s, str):
128 s = str.__str__(s)
129 else:
130 s = unicode.__getnewargs__(s)[0]
131 def replace(match):
132 s = match.group(0)
133 try:
134 return ESCAPE_DCT[s]
135 except KeyError:
136 n = ord(s)
137 if n < 0x10000:
138 return '\\u%04x' % (n,)
139 else:
140 # surrogate pair
141 n -= 0x10000
142 s1 = 0xd800 | ((n >> 10) & 0x3ff)
143 s2 = 0xdc00 | (n & 0x3ff)
144 return '\\u%04x\\u%04x' % (s1, s2)
145 return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
146
147
148encode_basestring_ascii = (
149 c_encode_basestring_ascii or py_encode_basestring_ascii)
150
151encode_basestring = (
152 c_encode_basestring or py_encode_basestring)
153
154class JSONEncoder(object):
155 """Extensible JSON <http://json.org> encoder for Python data structures.
156
157 Supports the following objects and types by default:
158
159 +-------------------+---------------+
160 | Python | JSON |
161 +===================+===============+
162 | dict, namedtuple | object |
163 +-------------------+---------------+
164 | list, tuple | array |
165 +-------------------+---------------+
166 | str, unicode | string |
167 +-------------------+---------------+
168 | int, long, float | number |
169 +-------------------+---------------+
170 | True | true |
171 +-------------------+---------------+
172 | False | false |
173 +-------------------+---------------+
174 | None | null |
175 +-------------------+---------------+
176
177 To extend this to recognize other objects, subclass and implement a
178 ``.default()`` method with another method that returns a serializable
179 object for ``o`` if possible, otherwise it should call the superclass
180 implementation (to raise ``TypeError``).
181
182 """
183 item_separator = ', '
184 key_separator = ': '
185
186 def __init__(self, skipkeys=False, ensure_ascii=True,
187 check_circular=True, allow_nan=False, sort_keys=False,
188 indent=None, separators=None, encoding='utf-8', default=None,
189 use_decimal=True, namedtuple_as_object=True,
190 tuple_as_array=True, bigint_as_string=False,
191 item_sort_key=None, for_json=False, ignore_nan=False,
192 int_as_string_bitcount=None, iterable_as_array=False):
193 """Constructor for JSONEncoder, with sensible defaults.
194
195 If skipkeys is false, then it is a TypeError to attempt
196 encoding of keys that are not str, int, long, float or None. If
197 skipkeys is True, such items are simply skipped.
198
199 If ensure_ascii is true, the output is guaranteed to be str
200 objects with all incoming unicode characters escaped. If
201 ensure_ascii is false, the output will be unicode object.
202
203 If check_circular is true, then lists, dicts, and custom encoded
204 objects will be checked for circular references during encoding to
205 prevent an infinite recursion (which would cause an OverflowError).
206 Otherwise, no such check takes place.
207
208 If allow_nan is true (default: False), then out of range float
209 values (nan, inf, -inf) will be serialized to
210 their JavaScript equivalents (NaN, Infinity, -Infinity)
211 instead of raising a ValueError. See
212 ignore_nan for ECMA-262 compliant behavior.
213
214 If sort_keys is true, then the output of dictionaries will be
215 sorted by key; this is useful for regression tests to ensure
216 that JSON serializations can be compared on a day-to-day basis.
217
218 If indent is a string, then JSON array elements and object members
219 will be pretty-printed with a newline followed by that string repeated
220 for each level of nesting. ``None`` (the default) selects the most compact
221 representation without any newlines. For backwards compatibility with
222 versions of simplejson earlier than 2.1.0, an integer is also accepted
223 and is converted to a string with that many spaces.
224
225 If specified, separators should be an (item_separator, key_separator)
226 tuple. The default is (', ', ': ') if *indent* is ``None`` and
227 (',', ': ') otherwise. To get the most compact JSON representation,
228 you should specify (',', ':') to eliminate whitespace.
229
230 If specified, default is a function that gets called for objects
231 that can't otherwise be serialized. It should return a JSON encodable
232 version of the object or raise a ``TypeError``.
233
234 If encoding is not None, then all input strings will be
235 transformed into unicode using that encoding prior to JSON-encoding.
236 The default is UTF-8.
237
238 If use_decimal is true (default: ``True``), ``decimal.Decimal`` will
239 be supported directly by the encoder. For the inverse, decode JSON
240 with ``parse_float=decimal.Decimal``.
241
242 If namedtuple_as_object is true (the default), objects with
243 ``_asdict()`` methods will be encoded as JSON objects.
244
245 If tuple_as_array is true (the default), tuple (and subclasses) will
246 be encoded as JSON arrays.
247
248 If *iterable_as_array* is true (default: ``False``),
249 any object not in the above table that implements ``__iter__()``
250 will be encoded as a JSON array.
251
252 If bigint_as_string is true (not the default), ints 2**53 and higher
253 or lower than -2**53 will be encoded as strings. This is to avoid the
254 rounding that happens in Javascript otherwise.
255
256 If int_as_string_bitcount is a positive number (n), then int of size
257 greater than or equal to 2**n or lower than or equal to -2**n will be
258 encoded as strings.
259
260 If specified, item_sort_key is a callable used to sort the items in
261 each dictionary. This is useful if you want to sort items other than
262 in alphabetical order by key.
263
264 If for_json is true (not the default), objects with a ``for_json()``
265 method will use the return value of that method for encoding as JSON
266 instead of the object.
267
268 If *ignore_nan* is true (default: ``False``), then out of range
269 :class:`float` values (``nan``, ``inf``, ``-inf``) will be serialized
270 as ``null`` in compliance with the ECMA-262 specification. If true,
271 this will override *allow_nan*.
272
273 """
274
275 self.skipkeys = skipkeys
276 self.ensure_ascii = ensure_ascii
277 self.check_circular = check_circular
278 self.allow_nan = allow_nan
279 self.sort_keys = sort_keys
280 self.use_decimal = use_decimal
281 self.namedtuple_as_object = namedtuple_as_object
282 self.tuple_as_array = tuple_as_array
283 self.iterable_as_array = iterable_as_array
284 self.bigint_as_string = bigint_as_string
285 self.item_sort_key = item_sort_key
286 self.for_json = for_json
287 self.ignore_nan = ignore_nan
288 self.int_as_string_bitcount = int_as_string_bitcount
289 if indent is not None and not isinstance(indent, string_types):
290 indent = indent * ' '
291 self.indent = indent
292 if separators is not None:
293 self.item_separator, self.key_separator = separators
294 elif indent is not None:
295 self.item_separator = ','
296 if default is not None:
297 self.default = default
298 self.encoding = encoding
299
300 def default(self, o):
301 """Implement this method in a subclass such that it returns
302 a serializable object for ``o``, or calls the base implementation
303 (to raise a ``TypeError``).
304
305 For example, to support arbitrary iterators, you could
306 implement default like this::
307
308 def default(self, o):
309 try:
310 iterable = iter(o)
311 except TypeError:
312 pass
313 else:
314 return list(iterable)
315 return JSONEncoder.default(self, o)
316
317 """
318 raise TypeError('Object of type %s is not JSON serializable' %
319 o.__class__.__name__)
320
321 def encode(self, o):
322 """Return a JSON string representation of a Python data structure.
323
324 >>> from simplejson import JSONEncoder
325 >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
326 '{"foo": ["bar", "baz"]}'
327
328 """
329 # This is for extremely simple cases and benchmarks.
330 if isinstance(o, binary_type):
331 _encoding = self.encoding
332 if (_encoding is not None and not (_encoding == 'utf-8')):
333 o = text_type(o, _encoding)
334 if isinstance(o, string_types):
335 if self.ensure_ascii:
336 return encode_basestring_ascii(o)
337 else:
338 return encode_basestring(o)
339 # This doesn't pass the iterator directly to ''.join() because the
340 # exceptions aren't as detailed. The list call should be roughly
341 # equivalent to the PySequence_Fast that ''.join() would do.
342 chunks = self.iterencode(o)
343 if not isinstance(chunks, (list, tuple)):
344 chunks = list(chunks)
345 if self.ensure_ascii:
346 return ''.join(chunks)
347 else:
348 return u''.join(chunks)
349
350 def iterencode(self, o):
351 """Encode the given object and yield each string
352 representation as available.
353
354 For example::
355
356 for chunk in JSONEncoder().iterencode(bigobject):
357 mysocket.write(chunk)
358
359 """
360 if self.check_circular:
361 markers = {}
362 else:
363 markers = None
364 if self.ensure_ascii:
365 _encoder = encode_basestring_ascii
366 else:
367 _encoder = encode_basestring
368 if self.encoding != 'utf-8' and self.encoding is not None:
369 def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
370 if isinstance(o, binary_type):
371 o = text_type(o, _encoding)
372 return _orig_encoder(o)
373
374 def floatstr(o, allow_nan=self.allow_nan, ignore_nan=self.ignore_nan,
375 _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf):
376 # Check for specials. Note that this type of test is processor
377 # and/or platform-specific, so do tests which don't depend on
378 # the internals.
379
380 if o != o:
381 text = 'NaN'
382 elif o == _inf:
383 text = 'Infinity'
384 elif o == _neginf:
385 text = '-Infinity'
386 else:
387 if type(o) != float:
388 # See #118, do not trust custom str/repr
389 o = float(o)
390 return _repr(o)
391
392 if ignore_nan:
393 text = 'null'
394 elif not allow_nan:
395 raise ValueError(
396 "Out of range float values are not JSON compliant: " +
397 repr(o))
398
399 return text
400
401 key_memo = {}
402 int_as_string_bitcount = (
403 53 if self.bigint_as_string else self.int_as_string_bitcount)
404 if c_make_encoder is not None:
405 _iterencode = c_make_encoder(
406 markers, self.default, _encoder, self.indent,
407 self.key_separator, self.item_separator, self.sort_keys,
408 self.skipkeys, self.allow_nan, key_memo, self.use_decimal,
409 self.namedtuple_as_object, self.tuple_as_array,
410 int_as_string_bitcount,
411 self.item_sort_key, self.encoding, self.for_json,
412 self.ignore_nan, decimal.Decimal, self.iterable_as_array)
413 else:
414 _iterencode = _make_iterencode(
415 markers, self.default, _encoder, self.indent, floatstr,
416 self.key_separator, self.item_separator, self.sort_keys,
417 self.skipkeys, self.use_decimal,
418 self.namedtuple_as_object, self.tuple_as_array,
419 int_as_string_bitcount,
420 self.item_sort_key, self.encoding, self.for_json,
421 self.iterable_as_array, Decimal=decimal.Decimal)
422 try:
423 return _iterencode(o, 0)
424 finally:
425 key_memo.clear()
426
427
428class JSONEncoderForHTML(JSONEncoder):
429 """An encoder that produces JSON safe to embed in HTML.
430
431 To embed JSON content in, say, a script tag on a web page, the
432 characters &, < and > should be escaped. They cannot be escaped
433 with the usual entities (e.g. &) because they are not expanded
434 within <script> tags.
435
436 This class also escapes the line separator and paragraph separator
437 characters U+2028 and U+2029, irrespective of the ensure_ascii setting,
438 as these characters are not valid in JavaScript strings (see
439 http://timelessrepo.com/json-isnt-a-javascript-subset).
440 """
441
442 def encode(self, o):
443 # Override JSONEncoder.encode because it has hacks for
444 # performance that make things more complicated.
445 chunks = self.iterencode(o)
446 if self.ensure_ascii:
447 return ''.join(chunks)
448 else:
449 return u''.join(chunks)
450
451 def iterencode(self, o):
452 chunks = super(JSONEncoderForHTML, self).iterencode(o)
453 for chunk in chunks:
454 chunk = chunk.replace('&', '\\u0026')
455 chunk = chunk.replace('<', '\\u003c')
456 chunk = chunk.replace('>', '\\u003e')
457
458 if not self.ensure_ascii:
459 chunk = chunk.replace(u'\u2028', '\\u2028')
460 chunk = chunk.replace(u'\u2029', '\\u2029')
461
462 yield chunk
463
464
465def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
466 _key_separator, _item_separator, _sort_keys, _skipkeys,
467 _use_decimal, _namedtuple_as_object, _tuple_as_array,
468 _int_as_string_bitcount, _item_sort_key,
469 _encoding,_for_json,
470 _iterable_as_array,
471 ## HACK: hand-optimized bytecode; turn globals into locals
472 _PY3=PY3,
473 ValueError=ValueError,
474 string_types=string_types,
475 Decimal=None,
476 dict=dict,
477 _dict_types=_dict_types,
478 float=float,
479 id=id,
480 integer_types=integer_types,
481 isinstance=isinstance,
482 list=list,
483 str=str,
484 tuple=tuple,
485 iter=iter,
486 ):
487 if _use_decimal and Decimal is None:
488 Decimal = decimal.Decimal
489 if _item_sort_key and not callable(_item_sort_key):
490 raise TypeError("item_sort_key must be None or callable")
491 elif _sort_keys and not _item_sort_key:
492 _item_sort_key = itemgetter(0)
493
494 if (_int_as_string_bitcount is not None and
495 (_int_as_string_bitcount <= 0 or
496 not isinstance(_int_as_string_bitcount, integer_types))):
497 raise TypeError("int_as_string_bitcount must be a positive integer")
498
499 def call_method(obj, method_name):
500 method = getattr(obj, method_name, None)
501 if callable(method):
502 try:
503 return (method(),)
504 except TypeError:
505 pass
506 return None
507
508 def _encode_int(value):
509 skip_quoting = (
510 _int_as_string_bitcount is None
511 or
512 _int_as_string_bitcount < 1
513 )
514 if type(value) not in integer_types:
515 # See #118, do not trust custom str/repr
516 value = int(value)
517 if (
518 skip_quoting or
519 (-1 << _int_as_string_bitcount)
520 < value <
521 (1 << _int_as_string_bitcount)
522 ):
523 return str(value)
524 return '"' + str(value) + '"'
525
526 def _iterencode_list(lst, _current_indent_level):
527 if not lst:
528 yield '[]'
529 return
530 if markers is not None:
531 markerid = id(lst)
532 if markerid in markers:
533 raise ValueError("Circular reference detected")
534 markers[markerid] = lst
535 buf = '['
536 if _indent is not None:
537 _current_indent_level += 1
538 newline_indent = '\n' + (_indent * _current_indent_level)
539 separator = _item_separator + newline_indent
540 buf += newline_indent
541 else:
542 newline_indent = None
543 separator = _item_separator
544 first = True
545 for i, value in enumerate(lst):
546 if first:
547 first = False
548 else:
549 buf = separator
550 try:
551 if isinstance(value, string_types):
552 yield buf + _encoder(value)
553 elif _PY3 and isinstance(value, bytes) and _encoding is not None:
554 yield buf + _encoder(value)
555 elif isinstance(value, RawJSON):
556 yield buf + value.encoded_json
557 elif value is None:
558 yield buf + 'null'
559 elif value is True:
560 yield buf + 'true'
561 elif value is False:
562 yield buf + 'false'
563 elif isinstance(value, integer_types):
564 yield buf + _encode_int(value)
565 elif isinstance(value, float):
566 yield buf + _floatstr(value)
567 elif _use_decimal and isinstance(value, Decimal):
568 yield buf + _encode_decimal(value, _floatstr)
569 else:
570 yield buf
571 for_json = _for_json and call_method(value, 'for_json')
572 if for_json:
573 chunks = _iterencode(for_json[0], _current_indent_level)
574 else:
575 _asdict = _namedtuple_as_object and call_method(value, '_asdict')
576 if _asdict:
577 dct = _asdict[0]
578 if not isinstance(dct, dict):
579 raise TypeError("_asdict() must return a dict, not %s" % (type(dct).__name__,))
580 chunks = _iterencode_dict(dct,
581 _current_indent_level)
582 elif isinstance(value, list):
583 chunks = _iterencode_list(value, _current_indent_level)
584 elif _tuple_as_array and isinstance(value, tuple):
585 chunks = _iterencode_list(value, _current_indent_level)
586 elif isinstance(value, _dict_types):
587 chunks = _iterencode_dict(value, _current_indent_level)
588 else:
589 chunks = _iterencode(value, _current_indent_level)
590 for chunk in chunks:
591 yield chunk
592 except BaseException as exc:
593 if _HAS_ADD_NOTE:
594 exc.add_note(
595 'when serializing %s item %d'
596 % (type(lst).__name__, i))
597 raise
598 if first:
599 # iterable_as_array misses the fast path at the top
600 yield '[]'
601 else:
602 if newline_indent is not None:
603 _current_indent_level -= 1
604 yield '\n' + (_indent * _current_indent_level)
605 yield ']'
606 if markers is not None:
607 del markers[markerid]
608
609 def _stringify_key(key):
610 if isinstance(key, string_types): # pragma: no cover
611 pass
612 elif _PY3 and isinstance(key, bytes) and _encoding is not None:
613 key = str(key, _encoding)
614 elif isinstance(key, float):
615 key = _floatstr(key)
616 elif key is True:
617 key = 'true'
618 elif key is False:
619 key = 'false'
620 elif key is None:
621 key = 'null'
622 elif isinstance(key, integer_types):
623 if type(key) not in integer_types:
624 # See #118, do not trust custom str/repr
625 key = int(key)
626 key = str(key)
627 elif _use_decimal and isinstance(key, Decimal):
628 key = _encode_decimal(key, _floatstr)
629 elif _skipkeys:
630 key = None
631 else:
632 raise TypeError('keys must be str, int, float, bool or None, '
633 'not %s' % key.__class__.__name__)
634 return key
635
636 def _iterencode_dict(dct, _current_indent_level):
637 if not dct:
638 yield '{}'
639 return
640 if markers is not None:
641 markerid = id(dct)
642 if markerid in markers:
643 raise ValueError("Circular reference detected")
644 markers[markerid] = dct
645 yield '{'
646 if _indent is not None:
647 _current_indent_level += 1
648 newline_indent = '\n' + (_indent * _current_indent_level)
649 item_separator = _item_separator + newline_indent
650 yield newline_indent
651 else:
652 newline_indent = None
653 item_separator = _item_separator
654 first = True
655 if _PY3:
656 iteritems = dct.items()
657 else:
658 iteritems = dct.iteritems()
659 if _item_sort_key:
660 items = []
661 for k, v in dct.items():
662 if not isinstance(k, string_types):
663 k = _stringify_key(k)
664 if k is None:
665 continue
666 items.append((k, v))
667 items.sort(key=_item_sort_key)
668 else:
669 items = iteritems
670 for key, value in items:
671 if not (_item_sort_key or isinstance(key, string_types)):
672 key = _stringify_key(key)
673 if key is None:
674 # _skipkeys must be True
675 continue
676 if first:
677 first = False
678 else:
679 yield item_separator
680 yield _encoder(key)
681 yield _key_separator
682 try:
683 if isinstance(value, string_types):
684 yield _encoder(value)
685 elif _PY3 and isinstance(value, bytes) and _encoding is not None:
686 yield _encoder(value)
687 elif isinstance(value, RawJSON):
688 yield value.encoded_json
689 elif value is None:
690 yield 'null'
691 elif value is True:
692 yield 'true'
693 elif value is False:
694 yield 'false'
695 elif isinstance(value, integer_types):
696 yield _encode_int(value)
697 elif isinstance(value, float):
698 yield _floatstr(value)
699 elif _use_decimal and isinstance(value, Decimal):
700 yield _encode_decimal(value, _floatstr)
701 else:
702 for_json = _for_json and call_method(value, 'for_json')
703 if for_json:
704 chunks = _iterencode(for_json[0], _current_indent_level)
705 else:
706 _asdict = _namedtuple_as_object and call_method(value, '_asdict')
707 if _asdict:
708 dct = _asdict[0]
709 if not isinstance(dct, dict):
710 raise TypeError("_asdict() must return a dict, not %s" % (type(dct).__name__,))
711 chunks = _iterencode_dict(dct,
712 _current_indent_level)
713 elif isinstance(value, list):
714 chunks = _iterencode_list(value, _current_indent_level)
715 elif _tuple_as_array and isinstance(value, tuple):
716 chunks = _iterencode_list(value, _current_indent_level)
717 elif isinstance(value, _dict_types):
718 chunks = _iterencode_dict(value, _current_indent_level)
719 else:
720 chunks = _iterencode(value, _current_indent_level)
721 for chunk in chunks:
722 yield chunk
723 except BaseException as exc:
724 if _HAS_ADD_NOTE:
725 exc.add_note(
726 'when serializing %s item %r'
727 % (type(dct).__name__, key))
728 raise
729 if newline_indent is not None:
730 _current_indent_level -= 1
731 yield '\n' + (_indent * _current_indent_level)
732 yield '}'
733 if markers is not None:
734 del markers[markerid]
735
736 def _iterencode(o, _current_indent_level):
737 if isinstance(o, string_types):
738 yield _encoder(o)
739 elif _PY3 and isinstance(o, bytes) and _encoding is not None:
740 yield _encoder(o)
741 elif isinstance(o, RawJSON):
742 yield o.encoded_json
743 elif o is None:
744 yield 'null'
745 elif o is True:
746 yield 'true'
747 elif o is False:
748 yield 'false'
749 elif isinstance(o, integer_types):
750 yield _encode_int(o)
751 elif isinstance(o, float):
752 yield _floatstr(o)
753 else:
754 for_json = _for_json and call_method(o, 'for_json')
755 if for_json:
756 for chunk in _iterencode(for_json[0], _current_indent_level):
757 yield chunk
758 else:
759 _asdict = _namedtuple_as_object and call_method(o, '_asdict')
760 if _asdict:
761 dct = _asdict[0]
762 if not isinstance(dct, dict):
763 raise TypeError("_asdict() must return a dict, not %s" % (type(dct).__name__,))
764 for chunk in _iterencode_dict(dct, _current_indent_level):
765 yield chunk
766 elif isinstance(o, list):
767 for chunk in _iterencode_list(o, _current_indent_level):
768 yield chunk
769 elif (_tuple_as_array and isinstance(o, tuple)):
770 for chunk in _iterencode_list(o, _current_indent_level):
771 yield chunk
772 elif isinstance(o, _dict_types):
773 for chunk in _iterencode_dict(o, _current_indent_level):
774 yield chunk
775 elif _use_decimal and isinstance(o, Decimal):
776 yield _encode_decimal(o, _floatstr)
777 else:
778 while _iterable_as_array:
779 # Markers are not checked here because it is valid for
780 # an iterable to return self.
781 try:
782 o = iter(o)
783 except TypeError:
784 break
785 for chunk in _iterencode_list(o, _current_indent_level):
786 yield chunk
787 return
788 if markers is not None:
789 markerid = id(o)
790 if markerid in markers:
791 raise ValueError("Circular reference detected")
792 markers[markerid] = o
793 try:
794 o = _default(o)
795 for chunk in _iterencode(o, _current_indent_level):
796 yield chunk
797 except BaseException as exc:
798 if _HAS_ADD_NOTE:
799 exc.add_note(
800 'when serializing %s object'
801 % type(o).__name__)
802 raise
803 if markers is not None:
804 del markers[markerid]
805
806 return _iterencode