Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/simplejson-4.1.1-py3.11-linux-x86_64.egg/simplejson/encoder.py: 19%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

434 statements  

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# dict-like types that should be encoded as JSON objects. 

47# frozendict is a builtin added in CPython 3.15 (PEP 814). 

48if sys.version_info >= (3, 15): 

49 _dict_types = (dict, frozendict) 

50else: 

51 _dict_types = dict 

52 

53def py_encode_basestring(s, _PY3=PY3, _q=u'"'): 

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

55 

56 """ 

57 if _PY3: 

58 if isinstance(s, bytes): 

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

60 elif type(s) is not str: 

61 # convert an str subclass instance to exact str 

62 # raise a TypeError otherwise 

63 s = str.__str__(s) 

64 else: 

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

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

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

68 # convert an str subclass instance to exact str 

69 # convert a unicode subclass instance to exact unicode 

70 # raise a TypeError otherwise 

71 if isinstance(s, str): 

72 s = str.__str__(s) 

73 else: 

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

75 def replace(match): 

76 return ESCAPE_DCT[match.group(0)] 

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

78 

79 

80def py_encode_basestring_ascii(s, _PY3=PY3): 

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

82 

83 """ 

84 if _PY3: 

85 if isinstance(s, bytes): 

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

87 elif type(s) is not str: 

88 # convert an str subclass instance to exact str 

89 # raise a TypeError otherwise 

90 s = str.__str__(s) 

91 else: 

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

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

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

95 # convert an str subclass instance to exact str 

96 # convert a unicode subclass instance to exact unicode 

97 # raise a TypeError otherwise 

98 if isinstance(s, str): 

99 s = str.__str__(s) 

100 else: 

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

102 def replace(match): 

103 s = match.group(0) 

104 try: 

105 return ESCAPE_DCT[s] 

106 except KeyError: 

107 n = ord(s) 

108 if n < 0x10000: 

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

110 else: 

111 # surrogate pair 

112 n -= 0x10000 

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

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

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

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

117 

118 

119encode_basestring_ascii = ( 

120 c_encode_basestring_ascii or py_encode_basestring_ascii) 

121 

122encode_basestring = ( 

123 c_encode_basestring or py_encode_basestring) 

124 

125class JSONEncoder(object): 

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

127 

128 Supports the following objects and types by default: 

129 

130 +-------------------+---------------+ 

131 | Python | JSON | 

132 +===================+===============+ 

133 | dict, namedtuple | object | 

134 +-------------------+---------------+ 

135 | list, tuple | array | 

136 +-------------------+---------------+ 

137 | str, unicode | string | 

138 +-------------------+---------------+ 

139 | int, long, float | number | 

140 +-------------------+---------------+ 

141 | True | true | 

142 +-------------------+---------------+ 

143 | False | false | 

144 +-------------------+---------------+ 

145 | None | null | 

146 +-------------------+---------------+ 

147 

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

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

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

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

152 

153 """ 

154 item_separator = ', ' 

155 key_separator = ': ' 

156 

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

158 check_circular=True, allow_nan=False, sort_keys=False, 

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

160 use_decimal=True, namedtuple_as_object=True, 

161 tuple_as_array=True, bigint_as_string=False, 

162 item_sort_key=None, for_json=False, ignore_nan=False, 

163 int_as_string_bitcount=None, iterable_as_array=False): 

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

165 

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

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

168 skipkeys is True, such items are simply skipped. 

169 

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

171 objects with all incoming unicode characters escaped. If 

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

173 

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

175 objects will be checked for circular references during encoding to 

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

177 Otherwise, no such check takes place. 

178 

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

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

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

182 instead of raising a ValueError. See 

183 ignore_nan for ECMA-262 compliant behavior. 

184 

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

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

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

188 

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

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

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

192 representation without any newlines. For backwards compatibility with 

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

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

195 

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

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

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

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

200 

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

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

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

204 

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

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

207 The default is UTF-8. 

208 

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

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

211 with ``parse_float=decimal.Decimal``. 

212 

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

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

215 

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

217 be encoded as JSON arrays. 

218 

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

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

221 will be encoded as a JSON array. 

222 

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

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

225 rounding that happens in Javascript otherwise. 

226 

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

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

229 encoded as strings. 

230 

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

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

233 in alphabetical order by key. 

234 

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

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

237 instead of the object. 

238 

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

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

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

242 this will override *allow_nan*. 

243 

244 """ 

245 

246 self.skipkeys = skipkeys 

247 self.ensure_ascii = ensure_ascii 

248 self.check_circular = check_circular 

249 self.allow_nan = allow_nan 

250 self.sort_keys = sort_keys 

251 self.use_decimal = use_decimal 

252 self.namedtuple_as_object = namedtuple_as_object 

253 self.tuple_as_array = tuple_as_array 

254 self.iterable_as_array = iterable_as_array 

255 self.bigint_as_string = bigint_as_string 

256 self.item_sort_key = item_sort_key 

257 self.for_json = for_json 

258 self.ignore_nan = ignore_nan 

259 self.int_as_string_bitcount = int_as_string_bitcount 

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

261 indent = indent * ' ' 

262 self.indent = indent 

263 if separators is not None: 

264 self.item_separator, self.key_separator = separators 

265 elif indent is not None: 

266 self.item_separator = ',' 

267 if default is not None: 

268 self.default = default 

269 self.encoding = encoding 

270 

271 def default(self, o): 

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

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

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

275 

276 For example, to support arbitrary iterators, you could 

277 implement default like this:: 

278 

279 def default(self, o): 

280 try: 

281 iterable = iter(o) 

282 except TypeError: 

283 pass 

284 else: 

285 return list(iterable) 

286 return JSONEncoder.default(self, o) 

287 

288 """ 

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

290 o.__class__.__name__) 

291 

292 def encode(self, o): 

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

294 

295 >>> from simplejson import JSONEncoder 

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

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

298 

299 """ 

300 # This is for extremely simple cases and benchmarks. 

301 if isinstance(o, binary_type): 

302 _encoding = self.encoding 

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

304 o = text_type(o, _encoding) 

305 if isinstance(o, string_types): 

306 if self.ensure_ascii: 

307 return encode_basestring_ascii(o) 

308 else: 

309 return encode_basestring(o) 

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

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

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

313 chunks = self.iterencode(o) 

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

315 chunks = list(chunks) 

316 if self.ensure_ascii: 

317 return ''.join(chunks) 

318 else: 

319 return u''.join(chunks) 

320 

321 def iterencode(self, o): 

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

323 representation as available. 

324 

325 For example:: 

326 

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

328 mysocket.write(chunk) 

329 

330 """ 

331 if self.check_circular: 

332 markers = {} 

333 else: 

334 markers = None 

335 if self.ensure_ascii: 

336 _encoder = encode_basestring_ascii 

337 else: 

338 _encoder = encode_basestring 

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

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

341 if isinstance(o, binary_type): 

342 o = text_type(o, _encoding) 

343 return _orig_encoder(o) 

344 

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

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

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

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

349 # the internals. 

350 

351 if o != o: 

352 text = 'NaN' 

353 elif o == _inf: 

354 text = 'Infinity' 

355 elif o == _neginf: 

356 text = '-Infinity' 

357 else: 

358 if type(o) != float: 

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

360 o = float(o) 

361 return _repr(o) 

362 

363 if ignore_nan: 

364 text = 'null' 

365 elif not allow_nan: 

366 raise ValueError( 

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

368 repr(o)) 

369 

370 return text 

371 

372 key_memo = {} 

373 int_as_string_bitcount = ( 

374 53 if self.bigint_as_string else self.int_as_string_bitcount) 

375 if c_make_encoder is not None: 

376 _iterencode = c_make_encoder( 

377 markers, self.default, _encoder, self.indent, 

378 self.key_separator, self.item_separator, self.sort_keys, 

379 self.skipkeys, self.allow_nan, key_memo, self.use_decimal, 

380 self.namedtuple_as_object, self.tuple_as_array, 

381 int_as_string_bitcount, 

382 self.item_sort_key, self.encoding, self.for_json, 

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

384 else: 

385 _iterencode = _make_iterencode( 

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

387 self.key_separator, self.item_separator, self.sort_keys, 

388 self.skipkeys, self.use_decimal, 

389 self.namedtuple_as_object, self.tuple_as_array, 

390 int_as_string_bitcount, 

391 self.item_sort_key, self.encoding, self.for_json, 

392 self.iterable_as_array, Decimal=decimal.Decimal) 

393 try: 

394 return _iterencode(o, 0) 

395 finally: 

396 key_memo.clear() 

397 

398 

399class JSONEncoderForHTML(JSONEncoder): 

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

401 

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

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

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

405 within <script> tags. 

406 

407 This class also escapes the line separator and paragraph separator 

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

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

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

411 """ 

412 

413 def encode(self, o): 

414 # Override JSONEncoder.encode because it has hacks for 

415 # performance that make things more complicated. 

416 chunks = self.iterencode(o) 

417 if self.ensure_ascii: 

418 return ''.join(chunks) 

419 else: 

420 return u''.join(chunks) 

421 

422 def iterencode(self, o): 

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

424 for chunk in chunks: 

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

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

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

428 

429 if not self.ensure_ascii: 

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

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

432 

433 yield chunk 

434 

435 

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

437 _key_separator, _item_separator, _sort_keys, _skipkeys, 

438 _use_decimal, _namedtuple_as_object, _tuple_as_array, 

439 _int_as_string_bitcount, _item_sort_key, 

440 _encoding,_for_json, 

441 _iterable_as_array, 

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

443 _PY3=PY3, 

444 ValueError=ValueError, 

445 string_types=string_types, 

446 Decimal=None, 

447 dict=dict, 

448 _dict_types=_dict_types, 

449 float=float, 

450 id=id, 

451 integer_types=integer_types, 

452 isinstance=isinstance, 

453 list=list, 

454 str=str, 

455 tuple=tuple, 

456 iter=iter, 

457 ): 

458 if _use_decimal and Decimal is None: 

459 Decimal = decimal.Decimal 

460 if _item_sort_key and not callable(_item_sort_key): 

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

462 elif _sort_keys and not _item_sort_key: 

463 _item_sort_key = itemgetter(0) 

464 

465 if (_int_as_string_bitcount is not None and 

466 (_int_as_string_bitcount <= 0 or 

467 not isinstance(_int_as_string_bitcount, integer_types))): 

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

469 

470 def call_method(obj, method_name): 

471 method = getattr(obj, method_name, None) 

472 if callable(method): 

473 try: 

474 return (method(),) 

475 except TypeError: 

476 pass 

477 return None 

478 

479 def _encode_int(value): 

480 skip_quoting = ( 

481 _int_as_string_bitcount is None 

482 or 

483 _int_as_string_bitcount < 1 

484 ) 

485 if type(value) not in integer_types: 

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

487 value = int(value) 

488 if ( 

489 skip_quoting or 

490 (-1 << _int_as_string_bitcount) 

491 < value < 

492 (1 << _int_as_string_bitcount) 

493 ): 

494 return str(value) 

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

496 

497 def _iterencode_list(lst, _current_indent_level): 

498 if not lst: 

499 yield '[]' 

500 return 

501 if markers is not None: 

502 markerid = id(lst) 

503 if markerid in markers: 

504 raise ValueError("Circular reference detected") 

505 markers[markerid] = lst 

506 buf = '[' 

507 if _indent is not None: 

508 _current_indent_level += 1 

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

510 separator = _item_separator + newline_indent 

511 buf += newline_indent 

512 else: 

513 newline_indent = None 

514 separator = _item_separator 

515 first = True 

516 for i, value in enumerate(lst): 

517 if first: 

518 first = False 

519 else: 

520 buf = separator 

521 try: 

522 if isinstance(value, string_types): 

523 yield buf + _encoder(value) 

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

525 yield buf + _encoder(value) 

526 elif isinstance(value, RawJSON): 

527 yield buf + value.encoded_json 

528 elif value is None: 

529 yield buf + 'null' 

530 elif value is True: 

531 yield buf + 'true' 

532 elif value is False: 

533 yield buf + 'false' 

534 elif isinstance(value, integer_types): 

535 yield buf + _encode_int(value) 

536 elif isinstance(value, float): 

537 yield buf + _floatstr(value) 

538 elif _use_decimal and isinstance(value, Decimal): 

539 yield buf + str(value) 

540 else: 

541 yield buf 

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

543 if for_json: 

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

545 else: 

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

547 if _asdict: 

548 dct = _asdict[0] 

549 if not isinstance(dct, dict): 

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

551 chunks = _iterencode_dict(dct, 

552 _current_indent_level) 

553 elif isinstance(value, list): 

554 chunks = _iterencode_list(value, _current_indent_level) 

555 elif _tuple_as_array and isinstance(value, tuple): 

556 chunks = _iterencode_list(value, _current_indent_level) 

557 elif isinstance(value, _dict_types): 

558 chunks = _iterencode_dict(value, _current_indent_level) 

559 else: 

560 chunks = _iterencode(value, _current_indent_level) 

561 for chunk in chunks: 

562 yield chunk 

563 except BaseException as exc: 

564 if _HAS_ADD_NOTE: 

565 exc.add_note( 

566 'when serializing %s item %d' 

567 % (type(lst).__name__, i)) 

568 raise 

569 if first: 

570 # iterable_as_array misses the fast path at the top 

571 yield '[]' 

572 else: 

573 if newline_indent is not None: 

574 _current_indent_level -= 1 

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

576 yield ']' 

577 if markers is not None: 

578 del markers[markerid] 

579 

580 def _stringify_key(key): 

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

582 pass 

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

584 key = str(key, _encoding) 

585 elif isinstance(key, float): 

586 key = _floatstr(key) 

587 elif key is True: 

588 key = 'true' 

589 elif key is False: 

590 key = 'false' 

591 elif key is None: 

592 key = 'null' 

593 elif isinstance(key, integer_types): 

594 if type(key) not in integer_types: 

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

596 key = int(key) 

597 key = str(key) 

598 elif _use_decimal and isinstance(key, Decimal): 

599 key = str(key) 

600 elif _skipkeys: 

601 key = None 

602 else: 

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

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

605 return key 

606 

607 def _iterencode_dict(dct, _current_indent_level): 

608 if not dct: 

609 yield '{}' 

610 return 

611 if markers is not None: 

612 markerid = id(dct) 

613 if markerid in markers: 

614 raise ValueError("Circular reference detected") 

615 markers[markerid] = dct 

616 yield '{' 

617 if _indent is not None: 

618 _current_indent_level += 1 

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

620 item_separator = _item_separator + newline_indent 

621 yield newline_indent 

622 else: 

623 newline_indent = None 

624 item_separator = _item_separator 

625 first = True 

626 if _PY3: 

627 iteritems = dct.items() 

628 else: 

629 iteritems = dct.iteritems() 

630 if _item_sort_key: 

631 items = [] 

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

633 if not isinstance(k, string_types): 

634 k = _stringify_key(k) 

635 if k is None: 

636 continue 

637 items.append((k, v)) 

638 items.sort(key=_item_sort_key) 

639 else: 

640 items = iteritems 

641 for key, value in items: 

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

643 key = _stringify_key(key) 

644 if key is None: 

645 # _skipkeys must be True 

646 continue 

647 if first: 

648 first = False 

649 else: 

650 yield item_separator 

651 yield _encoder(key) 

652 yield _key_separator 

653 try: 

654 if isinstance(value, string_types): 

655 yield _encoder(value) 

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

657 yield _encoder(value) 

658 elif isinstance(value, RawJSON): 

659 yield value.encoded_json 

660 elif value is None: 

661 yield 'null' 

662 elif value is True: 

663 yield 'true' 

664 elif value is False: 

665 yield 'false' 

666 elif isinstance(value, integer_types): 

667 yield _encode_int(value) 

668 elif isinstance(value, float): 

669 yield _floatstr(value) 

670 elif _use_decimal and isinstance(value, Decimal): 

671 yield str(value) 

672 else: 

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

674 if for_json: 

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

676 else: 

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

678 if _asdict: 

679 dct = _asdict[0] 

680 if not isinstance(dct, dict): 

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

682 chunks = _iterencode_dict(dct, 

683 _current_indent_level) 

684 elif isinstance(value, list): 

685 chunks = _iterencode_list(value, _current_indent_level) 

686 elif _tuple_as_array and isinstance(value, tuple): 

687 chunks = _iterencode_list(value, _current_indent_level) 

688 elif isinstance(value, _dict_types): 

689 chunks = _iterencode_dict(value, _current_indent_level) 

690 else: 

691 chunks = _iterencode(value, _current_indent_level) 

692 for chunk in chunks: 

693 yield chunk 

694 except BaseException as exc: 

695 if _HAS_ADD_NOTE: 

696 exc.add_note( 

697 'when serializing %s item %r' 

698 % (type(dct).__name__, key)) 

699 raise 

700 if newline_indent is not None: 

701 _current_indent_level -= 1 

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

703 yield '}' 

704 if markers is not None: 

705 del markers[markerid] 

706 

707 def _iterencode(o, _current_indent_level): 

708 if isinstance(o, string_types): 

709 yield _encoder(o) 

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

711 yield _encoder(o) 

712 elif isinstance(o, RawJSON): 

713 yield o.encoded_json 

714 elif o is None: 

715 yield 'null' 

716 elif o is True: 

717 yield 'true' 

718 elif o is False: 

719 yield 'false' 

720 elif isinstance(o, integer_types): 

721 yield _encode_int(o) 

722 elif isinstance(o, float): 

723 yield _floatstr(o) 

724 else: 

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

726 if for_json: 

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

728 yield chunk 

729 else: 

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

731 if _asdict: 

732 dct = _asdict[0] 

733 if not isinstance(dct, dict): 

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

735 for chunk in _iterencode_dict(dct, _current_indent_level): 

736 yield chunk 

737 elif isinstance(o, list): 

738 for chunk in _iterencode_list(o, _current_indent_level): 

739 yield chunk 

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

741 for chunk in _iterencode_list(o, _current_indent_level): 

742 yield chunk 

743 elif isinstance(o, _dict_types): 

744 for chunk in _iterencode_dict(o, _current_indent_level): 

745 yield chunk 

746 elif _use_decimal and isinstance(o, Decimal): 

747 yield str(o) 

748 else: 

749 while _iterable_as_array: 

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

751 # an iterable to return self. 

752 try: 

753 o = iter(o) 

754 except TypeError: 

755 break 

756 for chunk in _iterencode_list(o, _current_indent_level): 

757 yield chunk 

758 return 

759 if markers is not None: 

760 markerid = id(o) 

761 if markerid in markers: 

762 raise ValueError("Circular reference detected") 

763 markers[markerid] = o 

764 try: 

765 o = _default(o) 

766 for chunk in _iterencode(o, _current_indent_level): 

767 yield chunk 

768 except BaseException as exc: 

769 if _HAS_ADD_NOTE: 

770 exc.add_note( 

771 'when serializing %s object' 

772 % type(o).__name__) 

773 raise 

774 if markers is not None: 

775 del markers[markerid] 

776 

777 return _iterencode