| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | """Implementation of JSONEncoder
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     from _json import encode_basestring_ascii as c_encode_basestring_ascii | 
					
						
							| 
									
										
										
										
											2013-07-04 17:43:24 -04:00
										 |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |     c_encode_basestring_ascii = None | 
					
						
							| 
									
										
										
										
											2015-01-11 16:41:01 +01:00
										 |  |  | try: | 
					
						
							|  |  |  |     from _json import encode_basestring as c_encode_basestring | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     c_encode_basestring = None | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  | try: | 
					
						
							|  |  |  |     from _json import make_encoder as c_make_encoder | 
					
						
							| 
									
										
										
										
											2013-07-04 17:43:24 -04:00
										 |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     c_make_encoder = None | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') | 
					
						
							|  |  |  | ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  | HAS_UTF8 = re.compile(b'[\x80-\xff]') | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | ESCAPE_DCT = { | 
					
						
							|  |  |  |     '\\': '\\\\', | 
					
						
							|  |  |  |     '"': '\\"', | 
					
						
							|  |  |  |     '\b': '\\b', | 
					
						
							|  |  |  |     '\f': '\\f', | 
					
						
							|  |  |  |     '\n': '\\n', | 
					
						
							|  |  |  |     '\r': '\\r', | 
					
						
							|  |  |  |     '\t': '\\t', | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | for i in range(0x20): | 
					
						
							|  |  |  |     ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-21 17:49:06 -06:00
										 |  |  | INFINITY = float('inf') | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-11 16:41:01 +01:00
										 |  |  | def py_encode_basestring(s): | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |     """Return a JSON representation of a Python string
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     def replace(match): | 
					
						
							|  |  |  |         return ESCAPE_DCT[match.group(0)] | 
					
						
							|  |  |  |     return '"' + ESCAPE.sub(replace, s) + '"' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-11 16:41:01 +01:00
										 |  |  | encode_basestring = (c_encode_basestring or py_encode_basestring) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | def py_encode_basestring_ascii(s): | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     """Return an ASCII-only JSON representation of a Python string
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |     def replace(match): | 
					
						
							|  |  |  |         s = match.group(0) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             return ESCAPE_DCT[s] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             n = ord(s) | 
					
						
							|  |  |  |             if n < 0x10000: | 
					
						
							|  |  |  |                 return '\\u{0:04x}'.format(n) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |                 #return '\\u%04x' % (n,) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 # surrogate pair | 
					
						
							|  |  |  |                 n -= 0x10000 | 
					
						
							|  |  |  |                 s1 = 0xd800 | ((n >> 10) & 0x3ff) | 
					
						
							|  |  |  |                 s2 = 0xdc00 | (n & 0x3ff) | 
					
						
							|  |  |  |                 return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     return '"' + ESCAPE_ASCII.sub(replace, s) + '"' | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  | encode_basestring_ascii = ( | 
					
						
							|  |  |  |     c_encode_basestring_ascii or py_encode_basestring_ascii) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class JSONEncoder(object): | 
					
						
							|  |  |  |     """Extensible JSON <http://json.org> encoder for Python data structures.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Supports the following objects and types by default: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     +-------------------+---------------+ | 
					
						
							|  |  |  |     | Python            | JSON          | | 
					
						
							|  |  |  |     +===================+===============+ | 
					
						
							|  |  |  |     | dict              | object        | | 
					
						
							|  |  |  |     +-------------------+---------------+ | 
					
						
							|  |  |  |     | list, tuple       | array         | | 
					
						
							|  |  |  |     +-------------------+---------------+ | 
					
						
							| 
									
										
										
										
											2010-08-02 20:16:18 +00:00
										 |  |  |     | str               | string        | | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |     +-------------------+---------------+ | 
					
						
							| 
									
										
										
										
											2010-08-02 20:16:18 +00:00
										 |  |  |     | int, float        | number        | | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |     +-------------------+---------------+ | 
					
						
							|  |  |  |     | True              | true          | | 
					
						
							|  |  |  |     +-------------------+---------------+ | 
					
						
							|  |  |  |     | False             | false         | | 
					
						
							|  |  |  |     +-------------------+---------------+ | 
					
						
							|  |  |  |     | None              | null          | | 
					
						
							|  |  |  |     +-------------------+---------------+ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     To extend this to recognize other objects, subclass and implement a | 
					
						
							|  |  |  |     ``.default()`` method with another method that returns a serializable | 
					
						
							|  |  |  |     object for ``o`` if possible, otherwise it should call the superclass | 
					
						
							|  |  |  |     implementation (to raise ``TypeError``). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     item_separator = ', ' | 
					
						
							|  |  |  |     key_separator = ': ' | 
					
						
							| 
									
										
										
										
											2016-06-22 00:03:20 +03:00
										 |  |  |     def __init__(self, *, skipkeys=False, ensure_ascii=True, | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |             check_circular=True, allow_nan=True, sort_keys=False, | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             indent=None, separators=None, default=None): | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         """Constructor for JSONEncoder, with sensible defaults.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         If skipkeys is false, then it is a TypeError to attempt | 
					
						
							| 
									
										
										
										
											2010-08-02 20:16:18 +00:00
										 |  |  |         encoding of keys that are not str, int, float or None.  If | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         skipkeys is True, such items are simply skipped. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         If ensure_ascii is true, the output is guaranteed to be str | 
					
						
							| 
									
										
										
										
											2010-08-02 20:16:18 +00:00
										 |  |  |         objects with all incoming non-ASCII characters escaped.  If | 
					
						
							|  |  |  |         ensure_ascii is false, the output can contain non-ASCII characters. | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         If check_circular is true, then lists, dicts, and custom encoded | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         objects will be checked for circular references during encoding to | 
					
						
							|  |  |  |         prevent an infinite recursion (which would cause an OverflowError). | 
					
						
							|  |  |  |         Otherwise, no such check takes place. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         If allow_nan is true, then NaN, Infinity, and -Infinity will be | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         encoded as such.  This behavior is not JSON specification compliant, | 
					
						
							|  |  |  |         but is consistent with most JavaScript based encoders and decoders. | 
					
						
							|  |  |  |         Otherwise, it will be a ValueError to encode such floats. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         If sort_keys is true, then the output of dictionaries will be | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         sorted by key; this is useful for regression tests to ensure | 
					
						
							|  |  |  |         that JSON serializations can be compared on a day-to-day basis. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         If indent is a non-negative integer, then JSON array | 
					
						
							|  |  |  |         elements and object members will be pretty-printed with that | 
					
						
							|  |  |  |         indent level.  An indent level of 0 will only insert newlines. | 
					
						
							|  |  |  |         None is the most compact representation. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-29 00:42:56 +02:00
										 |  |  |         If specified, separators should be an (item_separator, key_separator) | 
					
						
							|  |  |  |         tuple.  The default is (', ', ': ') if *indent* is ``None`` and | 
					
						
							|  |  |  |         (',', ': ') otherwise.  To get the most compact JSON representation, | 
					
						
							|  |  |  |         you should specify (',', ':') to eliminate whitespace. | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         If specified, default is a function that gets called for objects | 
					
						
							|  |  |  |         that can't otherwise be serialized.  It should return a JSON encodable | 
					
						
							|  |  |  |         version of the object or raise a ``TypeError``. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         self.skipkeys = skipkeys | 
					
						
							|  |  |  |         self.ensure_ascii = ensure_ascii | 
					
						
							|  |  |  |         self.check_circular = check_circular | 
					
						
							|  |  |  |         self.allow_nan = allow_nan | 
					
						
							|  |  |  |         self.sort_keys = sort_keys | 
					
						
							|  |  |  |         self.indent = indent | 
					
						
							|  |  |  |         if separators is not None: | 
					
						
							|  |  |  |             self.item_separator, self.key_separator = separators | 
					
						
							| 
									
										
										
										
											2012-11-29 00:42:56 +02:00
										 |  |  |         elif indent is not None: | 
					
						
							|  |  |  |             self.item_separator = ',' | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         if default is not None: | 
					
						
							|  |  |  |             self.default = default | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     def default(self, o): | 
					
						
							|  |  |  |         """Implement this method in a subclass such that it returns
 | 
					
						
							|  |  |  |         a serializable object for ``o``, or calls the base implementation | 
					
						
							|  |  |  |         (to raise a ``TypeError``). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         For example, to support arbitrary iterators, you could | 
					
						
							|  |  |  |         implement default like this:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def default(self, o): | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     iterable = iter(o) | 
					
						
							|  |  |  |                 except TypeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     return list(iterable) | 
					
						
							| 
									
										
										
										
											2013-03-17 21:52:35 -04:00
										 |  |  |                 # Let the base class default method raise the TypeError | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |                 return JSONEncoder.default(self, o) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-11-25 17:38:20 +02:00
										 |  |  |         raise TypeError(f'Object of type {o.__class__.__name__} ' | 
					
						
							|  |  |  |                         f'is not JSON serializable') | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def encode(self, o): | 
					
						
							|  |  |  |         """Return a JSON string representation of a Python data structure.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |         >>> from json.encoder import JSONEncoder | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) | 
					
						
							|  |  |  |         '{"foo": ["bar", "baz"]}' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         # This is for extremely simple cases and benchmarks. | 
					
						
							|  |  |  |         if isinstance(o, str): | 
					
						
							|  |  |  |             if self.ensure_ascii: | 
					
						
							|  |  |  |                 return encode_basestring_ascii(o) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 return encode_basestring(o) | 
					
						
							|  |  |  |         # This doesn't pass the iterator directly to ''.join() because the | 
					
						
							|  |  |  |         # exceptions aren't as detailed.  The list call should be roughly | 
					
						
							|  |  |  |         # equivalent to the PySequence_Fast that ''.join() would do. | 
					
						
							|  |  |  |         chunks = self.iterencode(o, _one_shot=True) | 
					
						
							|  |  |  |         if not isinstance(chunks, (list, tuple)): | 
					
						
							|  |  |  |             chunks = list(chunks) | 
					
						
							|  |  |  |         return ''.join(chunks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def iterencode(self, o, _one_shot=False): | 
					
						
							|  |  |  |         """Encode the given object and yield each string
 | 
					
						
							|  |  |  |         representation as available. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for chunk in JSONEncoder().iterencode(bigobject): | 
					
						
							|  |  |  |                 mysocket.write(chunk) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         if self.check_circular: | 
					
						
							|  |  |  |             markers = {} | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             markers = None | 
					
						
							|  |  |  |         if self.ensure_ascii: | 
					
						
							|  |  |  |             _encoder = encode_basestring_ascii | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             _encoder = encode_basestring | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def floatstr(o, allow_nan=self.allow_nan, | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY): | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             # Check for specials.  Note that this type of test is processor | 
					
						
							|  |  |  |             # and/or platform-specific, so do tests which don't depend on the | 
					
						
							|  |  |  |             # internals. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if o != o: | 
					
						
							|  |  |  |                 text = 'NaN' | 
					
						
							|  |  |  |             elif o == _inf: | 
					
						
							|  |  |  |                 text = 'Infinity' | 
					
						
							|  |  |  |             elif o == _neginf: | 
					
						
							|  |  |  |                 text = '-Infinity' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 return _repr(o) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if not allow_nan: | 
					
						
							|  |  |  |                 raise ValueError( | 
					
						
							|  |  |  |                     "Out of range float values are not JSON compliant: " + | 
					
						
							|  |  |  |                     repr(o)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return text | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (_one_shot and c_make_encoder is not None | 
					
						
							| 
									
										
										
										
											2011-04-12 21:02:45 -04:00
										 |  |  |                 and self.indent is None): | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             _iterencode = c_make_encoder( | 
					
						
							|  |  |  |                 markers, self.default, _encoder, self.indent, | 
					
						
							|  |  |  |                 self.key_separator, self.item_separator, self.sort_keys, | 
					
						
							|  |  |  |                 self.skipkeys, self.allow_nan) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             _iterencode = _make_iterencode( | 
					
						
							|  |  |  |                 markers, self.default, _encoder, self.indent, floatstr, | 
					
						
							|  |  |  |                 self.key_separator, self.item_separator, self.sort_keys, | 
					
						
							|  |  |  |                 self.skipkeys, _one_shot) | 
					
						
							|  |  |  |         return _iterencode(o, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, | 
					
						
							|  |  |  |         _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, | 
					
						
							|  |  |  |         ## HACK: hand-optimized bytecode; turn globals into locals | 
					
						
							|  |  |  |         ValueError=ValueError, | 
					
						
							|  |  |  |         dict=dict, | 
					
						
							|  |  |  |         float=float, | 
					
						
							|  |  |  |         id=id, | 
					
						
							|  |  |  |         int=int, | 
					
						
							|  |  |  |         isinstance=isinstance, | 
					
						
							|  |  |  |         list=list, | 
					
						
							|  |  |  |         str=str, | 
					
						
							|  |  |  |         tuple=tuple, | 
					
						
							| 
									
										
										
										
											2019-05-06 22:29:40 +03:00
										 |  |  |         _intstr=int.__repr__, | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     ): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-31 08:00:16 +00:00
										 |  |  |     if _indent is not None and not isinstance(_indent, str): | 
					
						
							|  |  |  |         _indent = ' ' * _indent | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     def _iterencode_list(lst, _current_indent_level): | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         if not lst: | 
					
						
							|  |  |  |             yield '[]' | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if markers is not None: | 
					
						
							|  |  |  |             markerid = id(lst) | 
					
						
							|  |  |  |             if markerid in markers: | 
					
						
							|  |  |  |                 raise ValueError("Circular reference detected") | 
					
						
							|  |  |  |             markers[markerid] = lst | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         buf = '[' | 
					
						
							|  |  |  |         if _indent is not None: | 
					
						
							|  |  |  |             _current_indent_level += 1 | 
					
						
							| 
									
										
										
										
											2010-10-31 08:00:16 +00:00
										 |  |  |             newline_indent = '\n' + _indent * _current_indent_level | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             separator = _item_separator + newline_indent | 
					
						
							|  |  |  |             buf += newline_indent | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             newline_indent = None | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             separator = _item_separator | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         first = True | 
					
						
							|  |  |  |         for value in lst: | 
					
						
							|  |  |  |             if first: | 
					
						
							|  |  |  |                 first = False | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |                 buf = separator | 
					
						
							|  |  |  |             if isinstance(value, str): | 
					
						
							|  |  |  |                 yield buf + _encoder(value) | 
					
						
							|  |  |  |             elif value is None: | 
					
						
							|  |  |  |                 yield buf + 'null' | 
					
						
							|  |  |  |             elif value is True: | 
					
						
							|  |  |  |                 yield buf + 'true' | 
					
						
							|  |  |  |             elif value is False: | 
					
						
							|  |  |  |                 yield buf + 'false' | 
					
						
							|  |  |  |             elif isinstance(value, int): | 
					
						
							| 
									
										
										
										
											2019-05-06 22:29:40 +03:00
										 |  |  |                 # Subclasses of int/float may override __repr__, but we still | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |                 # want to encode them as integers/floats in JSON. One example | 
					
						
							|  |  |  |                 # within the standard library is IntEnum. | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 yield buf + _intstr(value) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             elif isinstance(value, float): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |                 # see comment above for int | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 yield buf + _floatstr(value) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 yield buf | 
					
						
							|  |  |  |                 if isinstance(value, (list, tuple)): | 
					
						
							|  |  |  |                     chunks = _iterencode_list(value, _current_indent_level) | 
					
						
							|  |  |  |                 elif isinstance(value, dict): | 
					
						
							|  |  |  |                     chunks = _iterencode_dict(value, _current_indent_level) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     chunks = _iterencode(value, _current_indent_level) | 
					
						
							| 
									
										
										
										
											2012-10-01 15:34:31 -07:00
										 |  |  |                 yield from chunks | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         if newline_indent is not None: | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             _current_indent_level -= 1 | 
					
						
							| 
									
										
										
										
											2010-10-31 08:00:16 +00:00
										 |  |  |             yield '\n' + _indent * _current_indent_level | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         yield ']' | 
					
						
							|  |  |  |         if markers is not None: | 
					
						
							|  |  |  |             del markers[markerid] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     def _iterencode_dict(dct, _current_indent_level): | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         if not dct: | 
					
						
							|  |  |  |             yield '{}' | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if markers is not None: | 
					
						
							|  |  |  |             markerid = id(dct) | 
					
						
							|  |  |  |             if markerid in markers: | 
					
						
							|  |  |  |                 raise ValueError("Circular reference detected") | 
					
						
							|  |  |  |             markers[markerid] = dct | 
					
						
							|  |  |  |         yield '{' | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         if _indent is not None: | 
					
						
							|  |  |  |             _current_indent_level += 1 | 
					
						
							| 
									
										
										
										
											2010-10-31 08:00:16 +00:00
										 |  |  |             newline_indent = '\n' + _indent * _current_indent_level | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             item_separator = _item_separator + newline_indent | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |             yield newline_indent | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             newline_indent = None | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             item_separator = _item_separator | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         first = True | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |         if _sort_keys: | 
					
						
							| 
									
										
										
										
											2018-07-07 08:55:03 +09:00
										 |  |  |             items = sorted(dct.items()) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             items = dct.items() | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         for key, value in items: | 
					
						
							|  |  |  |             if isinstance(key, str): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             # JavaScript is weakly typed for these, so it makes sense to | 
					
						
							|  |  |  |             # also allow them.  Many encoders seem to do something like this. | 
					
						
							|  |  |  |             elif isinstance(key, float): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |                 # see comment for int/float in _make_iterencode | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 key = _floatstr(key) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |             elif key is True: | 
					
						
							|  |  |  |                 key = 'true' | 
					
						
							|  |  |  |             elif key is False: | 
					
						
							|  |  |  |                 key = 'false' | 
					
						
							|  |  |  |             elif key is None: | 
					
						
							|  |  |  |                 key = 'null' | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             elif isinstance(key, int): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |                 # see comment for int/float in _make_iterencode | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 key = _intstr(key) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             elif _skipkeys: | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2017-11-25 17:38:20 +02:00
										 |  |  |                 raise TypeError(f'keys must be str, int, float, bool or None, ' | 
					
						
							|  |  |  |                                 f'not {key.__class__.__name__}') | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |             if first: | 
					
						
							|  |  |  |                 first = False | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 yield item_separator | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             yield _encoder(key) | 
					
						
							|  |  |  |             yield _key_separator | 
					
						
							|  |  |  |             if isinstance(value, str): | 
					
						
							|  |  |  |                 yield _encoder(value) | 
					
						
							|  |  |  |             elif value is None: | 
					
						
							|  |  |  |                 yield 'null' | 
					
						
							|  |  |  |             elif value is True: | 
					
						
							|  |  |  |                 yield 'true' | 
					
						
							|  |  |  |             elif value is False: | 
					
						
							|  |  |  |                 yield 'false' | 
					
						
							|  |  |  |             elif isinstance(value, int): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |                 # see comment for int/float in _make_iterencode | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 yield _intstr(value) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             elif isinstance(value, float): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |                 # see comment for int/float in _make_iterencode | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |                 yield _floatstr(value) | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 if isinstance(value, (list, tuple)): | 
					
						
							|  |  |  |                     chunks = _iterencode_list(value, _current_indent_level) | 
					
						
							|  |  |  |                 elif isinstance(value, dict): | 
					
						
							|  |  |  |                     chunks = _iterencode_dict(value, _current_indent_level) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     chunks = _iterencode(value, _current_indent_level) | 
					
						
							| 
									
										
										
										
											2012-10-01 15:34:31 -07:00
										 |  |  |                 yield from chunks | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         if newline_indent is not None: | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             _current_indent_level -= 1 | 
					
						
							| 
									
										
										
										
											2010-10-31 08:00:16 +00:00
										 |  |  |             yield '\n' + _indent * _current_indent_level | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         yield '}' | 
					
						
							|  |  |  |         if markers is not None: | 
					
						
							|  |  |  |             del markers[markerid] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     def _iterencode(o, _current_indent_level): | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         if isinstance(o, str): | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             yield _encoder(o) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         elif o is None: | 
					
						
							|  |  |  |             yield 'null' | 
					
						
							|  |  |  |         elif o is True: | 
					
						
							|  |  |  |             yield 'true' | 
					
						
							|  |  |  |         elif o is False: | 
					
						
							|  |  |  |             yield 'false' | 
					
						
							| 
									
										
										
										
											2010-07-28 16:39:41 +00:00
										 |  |  |         elif isinstance(o, int): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |             # see comment for int/float in _make_iterencode | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |             yield _intstr(o) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         elif isinstance(o, float): | 
					
						
							| 
									
										
										
										
											2013-08-10 13:01:45 -07:00
										 |  |  |             # see comment for int/float in _make_iterencode | 
					
						
							| 
									
										
										
										
											2016-04-10 14:41:19 +03:00
										 |  |  |             yield _floatstr(o) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         elif isinstance(o, (list, tuple)): | 
					
						
							| 
									
										
										
										
											2012-10-01 15:34:31 -07:00
										 |  |  |             yield from _iterencode_list(o, _current_indent_level) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         elif isinstance(o, dict): | 
					
						
							| 
									
										
										
										
											2012-10-01 15:34:31 -07:00
										 |  |  |             yield from _iterencode_dict(o, _current_indent_level) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             if markers is not None: | 
					
						
							|  |  |  |                 markerid = id(o) | 
					
						
							|  |  |  |                 if markerid in markers: | 
					
						
							|  |  |  |                     raise ValueError("Circular reference detected") | 
					
						
							|  |  |  |                 markers[markerid] = o | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |             o = _default(o) | 
					
						
							| 
									
										
										
										
											2012-10-01 15:34:31 -07:00
										 |  |  |             yield from _iterencode(o, _current_indent_level) | 
					
						
							| 
									
										
										
										
											2008-05-08 14:29:10 +00:00
										 |  |  |             if markers is not None: | 
					
						
							|  |  |  |                 del markers[markerid] | 
					
						
							| 
									
										
										
										
											2009-05-02 12:36:44 +00:00
										 |  |  |     return _iterencode |