Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/simplejson/encoder.py: 13%

412 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:20 +0000

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 

8from .compat import binary_type, text_type, string_types, integer_types, PY3 

9def _import_speedups(): 

10 try: 

11 from . import _speedups 

12 return _speedups.encode_basestring_ascii, _speedups.make_encoder 

13 except ImportError: 

14 return None, None 

15c_encode_basestring_ascii, c_make_encoder = _import_speedups() 

16 

17from .decoder import PosInf 

18from .raw_json import RawJSON 

19 

20ESCAPE = re.compile(r'[\x00-\x1f\\"]') 

21ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') 

22HAS_UTF8 = re.compile(r'[\x80-\xff]') 

23ESCAPE_DCT = { 

24 '\\': '\\\\', 

25 '"': '\\"', 

26 '\b': '\\b', 

27 '\f': '\\f', 

28 '\n': '\\n', 

29 '\r': '\\r', 

30 '\t': '\\t', 

31} 

32for i in range(0x20): 

33 #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) 

34 ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) 

35del i 

36 

37FLOAT_REPR = repr 

38 

39def encode_basestring(s, _PY3=PY3, _q=u'"'): 

40 """Return a JSON representation of a Python string 

41 

42 """ 

43 if _PY3: 

44 if isinstance(s, bytes): 

45 s = str(s, 'utf-8') 

46 elif type(s) is not str: 

47 # convert an str subclass instance to exact str 

48 # raise a TypeError otherwise 

49 s = str.__str__(s) 

50 else: 

51 if isinstance(s, str) and HAS_UTF8.search(s) is not None: 

52 s = unicode(s, 'utf-8') 

53 elif type(s) not in (str, unicode): 

54 # convert an str subclass instance to exact str 

55 # convert a unicode subclass instance to exact unicode 

56 # raise a TypeError otherwise 

57 if isinstance(s, str): 

58 s = str.__str__(s) 

59 else: 

60 s = unicode.__getnewargs__(s)[0] 

61 def replace(match): 

62 return ESCAPE_DCT[match.group(0)] 

63 return _q + ESCAPE.sub(replace, s) + _q 

64 

65 

66def py_encode_basestring_ascii(s, _PY3=PY3): 

67 """Return an ASCII-only JSON representation of a Python string 

68 

69 """ 

70 if _PY3: 

71 if isinstance(s, bytes): 

72 s = str(s, 'utf-8') 

73 elif type(s) is not str: 

74 # convert an str subclass instance to exact str 

75 # raise a TypeError otherwise 

76 s = str.__str__(s) 

77 else: 

78 if isinstance(s, str) and HAS_UTF8.search(s) is not None: 

79 s = unicode(s, 'utf-8') 

80 elif type(s) not in (str, unicode): 

81 # convert an str subclass instance to exact str 

82 # convert a unicode subclass instance to exact unicode 

83 # raise a TypeError otherwise 

84 if isinstance(s, str): 

85 s = str.__str__(s) 

86 else: 

87 s = unicode.__getnewargs__(s)[0] 

88 def replace(match): 

89 s = match.group(0) 

90 try: 

91 return ESCAPE_DCT[s] 

92 except KeyError: 

93 n = ord(s) 

94 if n < 0x10000: 

95 #return '\\u{0:04x}'.format(n) 

96 return '\\u%04x' % (n,) 

97 else: 

98 # surrogate pair 

99 n -= 0x10000 

100 s1 = 0xd800 | ((n >> 10) & 0x3ff) 

101 s2 = 0xdc00 | (n & 0x3ff) 

102 #return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) 

103 return '\\u%04x\\u%04x' % (s1, s2) 

104 return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' 

105 

106 

107encode_basestring_ascii = ( 

108 c_encode_basestring_ascii or py_encode_basestring_ascii) 

109 

110class JSONEncoder(object): 

111 """Extensible JSON <http://json.org> encoder for Python data structures. 

112 

113 Supports the following objects and types by default: 

114 

115 +-------------------+---------------+ 

116 | Python | JSON | 

117 +===================+===============+ 

118 | dict, namedtuple | object | 

119 +-------------------+---------------+ 

120 | list, tuple | array | 

121 +-------------------+---------------+ 

122 | str, unicode | string | 

123 +-------------------+---------------+ 

124 | int, long, float | number | 

125 +-------------------+---------------+ 

126 | True | true | 

127 +-------------------+---------------+ 

128 | False | false | 

129 +-------------------+---------------+ 

130 | None | null | 

131 +-------------------+---------------+ 

132 

133 To extend this to recognize other objects, subclass and implement a 

134 ``.default()`` method with another method that returns a serializable 

135 object for ``o`` if possible, otherwise it should call the superclass 

136 implementation (to raise ``TypeError``). 

137 

138 """ 

139 item_separator = ', ' 

140 key_separator = ': ' 

141 

142 def __init__(self, skipkeys=False, ensure_ascii=True, 

143 check_circular=True, allow_nan=False, sort_keys=False, 

144 indent=None, separators=None, encoding='utf-8', default=None, 

145 use_decimal=True, namedtuple_as_object=True, 

146 tuple_as_array=True, bigint_as_string=False, 

147 item_sort_key=None, for_json=False, ignore_nan=False, 

148 int_as_string_bitcount=None, iterable_as_array=False): 

149 """Constructor for JSONEncoder, with sensible defaults. 

150 

151 If skipkeys is false, then it is a TypeError to attempt 

152 encoding of keys that are not str, int, long, float or None. If 

153 skipkeys is True, such items are simply skipped. 

154 

155 If ensure_ascii is true, the output is guaranteed to be str 

156 objects with all incoming unicode characters escaped. If 

157 ensure_ascii is false, the output will be unicode object. 

158 

159 If check_circular is true, then lists, dicts, and custom encoded 

160 objects will be checked for circular references during encoding to 

161 prevent an infinite recursion (which would cause an OverflowError). 

162 Otherwise, no such check takes place. 

163 

164 If allow_nan is true (default: False), then out of range float 

165 values (nan, inf, -inf) will be serialized to 

166 their JavaScript equivalents (NaN, Infinity, -Infinity) 

167 instead of raising a ValueError. See 

168 ignore_nan for ECMA-262 compliant behavior. 

169 

170 If sort_keys is true, then the output of dictionaries will be 

171 sorted by key; this is useful for regression tests to ensure 

172 that JSON serializations can be compared on a day-to-day basis. 

173 

174 If indent is a string, then JSON array elements and object members 

175 will be pretty-printed with a newline followed by that string repeated 

176 for each level of nesting. ``None`` (the default) selects the most compact 

177 representation without any newlines. For backwards compatibility with 

178 versions of simplejson earlier than 2.1.0, an integer is also accepted 

179 and is converted to a string with that many spaces. 

180 

181 If specified, separators should be an (item_separator, key_separator) 

182 tuple. The default is (', ', ': ') if *indent* is ``None`` and 

183 (',', ': ') otherwise. To get the most compact JSON representation, 

184 you should specify (',', ':') to eliminate whitespace. 

185 

186 If specified, default is a function that gets called for objects 

187 that can't otherwise be serialized. It should return a JSON encodable 

188 version of the object or raise a ``TypeError``. 

189 

190 If encoding is not None, then all input strings will be 

191 transformed into unicode using that encoding prior to JSON-encoding. 

192 The default is UTF-8. 

193 

194 If use_decimal is true (default: ``True``), ``decimal.Decimal`` will 

195 be supported directly by the encoder. For the inverse, decode JSON 

196 with ``parse_float=decimal.Decimal``. 

197 

198 If namedtuple_as_object is true (the default), objects with 

199 ``_asdict()`` methods will be encoded as JSON objects. 

200 

201 If tuple_as_array is true (the default), tuple (and subclasses) will 

202 be encoded as JSON arrays. 

203 

204 If *iterable_as_array* is true (default: ``False``), 

205 any object not in the above table that implements ``__iter__()`` 

206 will be encoded as a JSON array. 

207 

208 If bigint_as_string is true (not the default), ints 2**53 and higher 

209 or lower than -2**53 will be encoded as strings. This is to avoid the 

210 rounding that happens in Javascript otherwise. 

211 

212 If int_as_string_bitcount is a positive number (n), then int of size 

213 greater than or equal to 2**n or lower than or equal to -2**n will be 

214 encoded as strings. 

215 

216 If specified, item_sort_key is a callable used to sort the items in 

217 each dictionary. This is useful if you want to sort items other than 

218 in alphabetical order by key. 

219 

220 If for_json is true (not the default), objects with a ``for_json()`` 

221 method will use the return value of that method for encoding as JSON 

222 instead of the object. 

223 

224 If *ignore_nan* is true (default: ``False``), then out of range 

225 :class:`float` values (``nan``, ``inf``, ``-inf``) will be serialized 

226 as ``null`` in compliance with the ECMA-262 specification. If true, 

227 this will override *allow_nan*. 

228 

229 """ 

230 

231 self.skipkeys = skipkeys 

232 self.ensure_ascii = ensure_ascii 

233 self.check_circular = check_circular 

234 self.allow_nan = allow_nan 

235 self.sort_keys = sort_keys 

236 self.use_decimal = use_decimal 

237 self.namedtuple_as_object = namedtuple_as_object 

238 self.tuple_as_array = tuple_as_array 

239 self.iterable_as_array = iterable_as_array 

240 self.bigint_as_string = bigint_as_string 

241 self.item_sort_key = item_sort_key 

242 self.for_json = for_json 

243 self.ignore_nan = ignore_nan 

244 self.int_as_string_bitcount = int_as_string_bitcount 

245 if indent is not None and not isinstance(indent, string_types): 

246 indent = indent * ' ' 

247 self.indent = indent 

248 if separators is not None: 

249 self.item_separator, self.key_separator = separators 

250 elif indent is not None: 

251 self.item_separator = ',' 

252 if default is not None: 

253 self.default = default 

254 self.encoding = encoding 

255 

256 def default(self, o): 

257 """Implement this method in a subclass such that it returns 

258 a serializable object for ``o``, or calls the base implementation 

259 (to raise a ``TypeError``). 

260 

261 For example, to support arbitrary iterators, you could 

262 implement default like this:: 

263 

264 def default(self, o): 

265 try: 

266 iterable = iter(o) 

267 except TypeError: 

268 pass 

269 else: 

270 return list(iterable) 

271 return JSONEncoder.default(self, o) 

272 

273 """ 

274 raise TypeError('Object of type %s is not JSON serializable' % 

275 o.__class__.__name__) 

276 

277 def encode(self, o): 

278 """Return a JSON string representation of a Python data structure. 

279 

280 >>> from simplejson import JSONEncoder 

281 >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) 

282 '{"foo": ["bar", "baz"]}' 

283 

284 """ 

285 # This is for extremely simple cases and benchmarks. 

286 if isinstance(o, binary_type): 

287 _encoding = self.encoding 

288 if (_encoding is not None and not (_encoding == 'utf-8')): 

289 o = text_type(o, _encoding) 

290 if isinstance(o, string_types): 

291 if self.ensure_ascii: 

292 return encode_basestring_ascii(o) 

293 else: 

294 return encode_basestring(o) 

295 # This doesn't pass the iterator directly to ''.join() because the 

296 # exceptions aren't as detailed. The list call should be roughly 

297 # equivalent to the PySequence_Fast that ''.join() would do. 

298 chunks = self.iterencode(o) 

299 if not isinstance(chunks, (list, tuple)): 

300 chunks = list(chunks) 

301 if self.ensure_ascii: 

302 return ''.join(chunks) 

303 else: 

304 return u''.join(chunks) 

305 

306 def iterencode(self, o): 

307 """Encode the given object and yield each string 

308 representation as available. 

309 

310 For example:: 

311 

312 for chunk in JSONEncoder().iterencode(bigobject): 

313 mysocket.write(chunk) 

314 

315 """ 

316 if self.check_circular: 

317 markers = {} 

318 else: 

319 markers = None 

320 if self.ensure_ascii: 

321 _encoder = encode_basestring_ascii 

322 else: 

323 _encoder = encode_basestring 

324 if self.encoding != 'utf-8' and self.encoding is not None: 

325 def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): 

326 if isinstance(o, binary_type): 

327 o = text_type(o, _encoding) 

328 return _orig_encoder(o) 

329 

330 def floatstr(o, allow_nan=self.allow_nan, ignore_nan=self.ignore_nan, 

331 _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf): 

332 # Check for specials. Note that this type of test is processor 

333 # and/or platform-specific, so do tests which don't depend on 

334 # the internals. 

335 

336 if o != o: 

337 text = 'NaN' 

338 elif o == _inf: 

339 text = 'Infinity' 

340 elif o == _neginf: 

341 text = '-Infinity' 

342 else: 

343 if type(o) != float: 

344 # See #118, do not trust custom str/repr 

345 o = float(o) 

346 return _repr(o) 

347 

348 if ignore_nan: 

349 text = 'null' 

350 elif not allow_nan: 

351 raise ValueError( 

352 "Out of range float values are not JSON compliant: " + 

353 repr(o)) 

354 

355 return text 

356 

357 key_memo = {} 

358 int_as_string_bitcount = ( 

359 53 if self.bigint_as_string else self.int_as_string_bitcount) 

360 if (c_make_encoder is not None and self.indent is None): 

361 _iterencode = c_make_encoder( 

362 markers, self.default, _encoder, self.indent, 

363 self.key_separator, self.item_separator, self.sort_keys, 

364 self.skipkeys, self.allow_nan, key_memo, self.use_decimal, 

365 self.namedtuple_as_object, self.tuple_as_array, 

366 int_as_string_bitcount, 

367 self.item_sort_key, self.encoding, self.for_json, 

368 self.ignore_nan, decimal.Decimal, self.iterable_as_array) 

369 else: 

370 _iterencode = _make_iterencode( 

371 markers, self.default, _encoder, self.indent, floatstr, 

372 self.key_separator, self.item_separator, self.sort_keys, 

373 self.skipkeys, self.use_decimal, 

374 self.namedtuple_as_object, self.tuple_as_array, 

375 int_as_string_bitcount, 

376 self.item_sort_key, self.encoding, self.for_json, 

377 self.iterable_as_array, Decimal=decimal.Decimal) 

378 try: 

379 return _iterencode(o, 0) 

380 finally: 

381 key_memo.clear() 

382 

383 

384class JSONEncoderForHTML(JSONEncoder): 

385 """An encoder that produces JSON safe to embed in HTML. 

386 

387 To embed JSON content in, say, a script tag on a web page, the 

388 characters &, < and > should be escaped. They cannot be escaped 

389 with the usual entities (e.g. &amp;) because they are not expanded 

390 within <script> tags. 

391 

392 This class also escapes the line separator and paragraph separator 

393 characters U+2028 and U+2029, irrespective of the ensure_ascii setting, 

394 as these characters are not valid in JavaScript strings (see 

395 http://timelessrepo.com/json-isnt-a-javascript-subset). 

396 """ 

397 

398 def encode(self, o): 

399 # Override JSONEncoder.encode because it has hacks for 

400 # performance that make things more complicated. 

401 chunks = self.iterencode(o) 

402 if self.ensure_ascii: 

403 return ''.join(chunks) 

404 else: 

405 return u''.join(chunks) 

406 

407 def iterencode(self, o): 

408 chunks = super(JSONEncoderForHTML, self).iterencode(o) 

409 for chunk in chunks: 

410 chunk = chunk.replace('&', '\\u0026') 

411 chunk = chunk.replace('<', '\\u003c') 

412 chunk = chunk.replace('>', '\\u003e') 

413 

414 if not self.ensure_ascii: 

415 chunk = chunk.replace(u'\u2028', '\\u2028') 

416 chunk = chunk.replace(u'\u2029', '\\u2029') 

417 

418 yield chunk 

419 

420 

421def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, 

422 _key_separator, _item_separator, _sort_keys, _skipkeys, 

423 _use_decimal, _namedtuple_as_object, _tuple_as_array, 

424 _int_as_string_bitcount, _item_sort_key, 

425 _encoding,_for_json, 

426 _iterable_as_array, 

427 ## HACK: hand-optimized bytecode; turn globals into locals 

428 _PY3=PY3, 

429 ValueError=ValueError, 

430 string_types=string_types, 

431 Decimal=None, 

432 dict=dict, 

433 float=float, 

434 id=id, 

435 integer_types=integer_types, 

436 isinstance=isinstance, 

437 list=list, 

438 str=str, 

439 tuple=tuple, 

440 iter=iter, 

441 ): 

442 if _use_decimal and Decimal is None: 

443 Decimal = decimal.Decimal 

444 if _item_sort_key and not callable(_item_sort_key): 

445 raise TypeError("item_sort_key must be None or callable") 

446 elif _sort_keys and not _item_sort_key: 

447 _item_sort_key = itemgetter(0) 

448 

449 if (_int_as_string_bitcount is not None and 

450 (_int_as_string_bitcount <= 0 or 

451 not isinstance(_int_as_string_bitcount, integer_types))): 

452 raise TypeError("int_as_string_bitcount must be a positive integer") 

453 

454 def call_method(obj, method_name): 

455 method = getattr(obj, method_name, None) 

456 if callable(method): 

457 try: 

458 return (method(),) 

459 except TypeError: 

460 pass 

461 return None 

462 

463 def _encode_int(value): 

464 skip_quoting = ( 

465 _int_as_string_bitcount is None 

466 or 

467 _int_as_string_bitcount < 1 

468 ) 

469 if type(value) not in integer_types: 

470 # See #118, do not trust custom str/repr 

471 value = int(value) 

472 if ( 

473 skip_quoting or 

474 (-1 << _int_as_string_bitcount) 

475 < value < 

476 (1 << _int_as_string_bitcount) 

477 ): 

478 return str(value) 

479 return '"' + str(value) + '"' 

480 

481 def _iterencode_list(lst, _current_indent_level): 

482 if not lst: 

483 yield '[]' 

484 return 

485 if markers is not None: 

486 markerid = id(lst) 

487 if markerid in markers: 

488 raise ValueError("Circular reference detected") 

489 markers[markerid] = lst 

490 buf = '[' 

491 if _indent is not None: 

492 _current_indent_level += 1 

493 newline_indent = '\n' + (_indent * _current_indent_level) 

494 separator = _item_separator + newline_indent 

495 buf += newline_indent 

496 else: 

497 newline_indent = None 

498 separator = _item_separator 

499 first = True 

500 for value in lst: 

501 if first: 

502 first = False 

503 else: 

504 buf = separator 

505 if isinstance(value, string_types): 

506 yield buf + _encoder(value) 

507 elif _PY3 and isinstance(value, bytes) and _encoding is not None: 

508 yield buf + _encoder(value) 

509 elif isinstance(value, RawJSON): 

510 yield buf + value.encoded_json 

511 elif value is None: 

512 yield buf + 'null' 

513 elif value is True: 

514 yield buf + 'true' 

515 elif value is False: 

516 yield buf + 'false' 

517 elif isinstance(value, integer_types): 

518 yield buf + _encode_int(value) 

519 elif isinstance(value, float): 

520 yield buf + _floatstr(value) 

521 elif _use_decimal and isinstance(value, Decimal): 

522 yield buf + str(value) 

523 else: 

524 yield buf 

525 for_json = _for_json and call_method(value, 'for_json') 

526 if for_json: 

527 chunks = _iterencode(for_json[0], _current_indent_level) 

528 elif isinstance(value, list): 

529 chunks = _iterencode_list(value, _current_indent_level) 

530 else: 

531 _asdict = _namedtuple_as_object and call_method(value, '_asdict') 

532 if _asdict: 

533 dct = _asdict[0] 

534 if not isinstance(dct, dict): 

535 raise TypeError("_asdict() must return a dict, not %s" % (type(dct).__name__,)) 

536 chunks = _iterencode_dict(dct, 

537 _current_indent_level) 

538 elif _tuple_as_array and isinstance(value, tuple): 

539 chunks = _iterencode_list(value, _current_indent_level) 

540 elif isinstance(value, dict): 

541 chunks = _iterencode_dict(value, _current_indent_level) 

542 else: 

543 chunks = _iterencode(value, _current_indent_level) 

544 for chunk in chunks: 

545 yield chunk 

546 if first: 

547 # iterable_as_array misses the fast path at the top 

548 yield '[]' 

549 else: 

550 if newline_indent is not None: 

551 _current_indent_level -= 1 

552 yield '\n' + (_indent * _current_indent_level) 

553 yield ']' 

554 if markers is not None: 

555 del markers[markerid] 

556 

557 def _stringify_key(key): 

558 if isinstance(key, string_types): # pragma: no cover 

559 pass 

560 elif _PY3 and isinstance(key, bytes) and _encoding is not None: 

561 key = str(key, _encoding) 

562 elif isinstance(key, float): 

563 key = _floatstr(key) 

564 elif key is True: 

565 key = 'true' 

566 elif key is False: 

567 key = 'false' 

568 elif key is None: 

569 key = 'null' 

570 elif isinstance(key, integer_types): 

571 if type(key) not in integer_types: 

572 # See #118, do not trust custom str/repr 

573 key = int(key) 

574 key = str(key) 

575 elif _use_decimal and isinstance(key, Decimal): 

576 key = str(key) 

577 elif _skipkeys: 

578 key = None 

579 else: 

580 raise TypeError('keys must be str, int, float, bool or None, ' 

581 'not %s' % key.__class__.__name__) 

582 return key 

583 

584 def _iterencode_dict(dct, _current_indent_level): 

585 if not dct: 

586 yield '{}' 

587 return 

588 if markers is not None: 

589 markerid = id(dct) 

590 if markerid in markers: 

591 raise ValueError("Circular reference detected") 

592 markers[markerid] = dct 

593 yield '{' 

594 if _indent is not None: 

595 _current_indent_level += 1 

596 newline_indent = '\n' + (_indent * _current_indent_level) 

597 item_separator = _item_separator + newline_indent 

598 yield newline_indent 

599 else: 

600 newline_indent = None 

601 item_separator = _item_separator 

602 first = True 

603 if _PY3: 

604 iteritems = dct.items() 

605 else: 

606 iteritems = dct.iteritems() 

607 if _item_sort_key: 

608 items = [] 

609 for k, v in dct.items(): 

610 if not isinstance(k, string_types): 

611 k = _stringify_key(k) 

612 if k is None: 

613 continue 

614 items.append((k, v)) 

615 items.sort(key=_item_sort_key) 

616 else: 

617 items = iteritems 

618 for key, value in items: 

619 if not (_item_sort_key or isinstance(key, string_types)): 

620 key = _stringify_key(key) 

621 if key is None: 

622 # _skipkeys must be True 

623 continue 

624 if first: 

625 first = False 

626 else: 

627 yield item_separator 

628 yield _encoder(key) 

629 yield _key_separator 

630 if isinstance(value, string_types): 

631 yield _encoder(value) 

632 elif _PY3 and isinstance(value, bytes) and _encoding is not None: 

633 yield _encoder(value) 

634 elif isinstance(value, RawJSON): 

635 yield value.encoded_json 

636 elif value is None: 

637 yield 'null' 

638 elif value is True: 

639 yield 'true' 

640 elif value is False: 

641 yield 'false' 

642 elif isinstance(value, integer_types): 

643 yield _encode_int(value) 

644 elif isinstance(value, float): 

645 yield _floatstr(value) 

646 elif _use_decimal and isinstance(value, Decimal): 

647 yield str(value) 

648 else: 

649 for_json = _for_json and call_method(value, 'for_json') 

650 if for_json: 

651 chunks = _iterencode(for_json[0], _current_indent_level) 

652 elif isinstance(value, list): 

653 chunks = _iterencode_list(value, _current_indent_level) 

654 else: 

655 _asdict = _namedtuple_as_object and call_method(value, '_asdict') 

656 if _asdict: 

657 dct = _asdict[0] 

658 if not isinstance(dct, dict): 

659 raise TypeError("_asdict() must return a dict, not %s" % (type(dct).__name__,)) 

660 chunks = _iterencode_dict(dct, 

661 _current_indent_level) 

662 elif _tuple_as_array and isinstance(value, tuple): 

663 chunks = _iterencode_list(value, _current_indent_level) 

664 elif isinstance(value, dict): 

665 chunks = _iterencode_dict(value, _current_indent_level) 

666 else: 

667 chunks = _iterencode(value, _current_indent_level) 

668 for chunk in chunks: 

669 yield chunk 

670 if newline_indent is not None: 

671 _current_indent_level -= 1 

672 yield '\n' + (_indent * _current_indent_level) 

673 yield '}' 

674 if markers is not None: 

675 del markers[markerid] 

676 

677 def _iterencode(o, _current_indent_level): 

678 if isinstance(o, string_types): 

679 yield _encoder(o) 

680 elif _PY3 and isinstance(o, bytes) and _encoding is not None: 

681 yield _encoder(o) 

682 elif isinstance(o, RawJSON): 

683 yield o.encoded_json 

684 elif o is None: 

685 yield 'null' 

686 elif o is True: 

687 yield 'true' 

688 elif o is False: 

689 yield 'false' 

690 elif isinstance(o, integer_types): 

691 yield _encode_int(o) 

692 elif isinstance(o, float): 

693 yield _floatstr(o) 

694 else: 

695 for_json = _for_json and call_method(o, 'for_json') 

696 if for_json: 

697 for chunk in _iterencode(for_json[0], _current_indent_level): 

698 yield chunk 

699 elif isinstance(o, list): 

700 for chunk in _iterencode_list(o, _current_indent_level): 

701 yield chunk 

702 else: 

703 _asdict = _namedtuple_as_object and call_method(o, '_asdict') 

704 if _asdict: 

705 dct = _asdict[0] 

706 if not isinstance(dct, dict): 

707 raise TypeError("_asdict() must return a dict, not %s" % (type(dct).__name__,)) 

708 for chunk in _iterencode_dict(dct, _current_indent_level): 

709 yield chunk 

710 elif (_tuple_as_array and isinstance(o, tuple)): 

711 for chunk in _iterencode_list(o, _current_indent_level): 

712 yield chunk 

713 elif isinstance(o, dict): 

714 for chunk in _iterencode_dict(o, _current_indent_level): 

715 yield chunk 

716 elif _use_decimal and isinstance(o, Decimal): 

717 yield str(o) 

718 else: 

719 while _iterable_as_array: 

720 # Markers are not checked here because it is valid for 

721 # an iterable to return self. 

722 try: 

723 o = iter(o) 

724 except TypeError: 

725 break 

726 for chunk in _iterencode_list(o, _current_indent_level): 

727 yield chunk 

728 return 

729 if markers is not None: 

730 markerid = id(o) 

731 if markerid in markers: 

732 raise ValueError("Circular reference detected") 

733 markers[markerid] = o 

734 o = _default(o) 

735 for chunk in _iterencode(o, _current_indent_level): 

736 yield chunk 

737 if markers is not None: 

738 del markers[markerid] 

739 

740 return _iterencode