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