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

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

479 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 

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. &amp;) 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