[issue4136] merge json library with latest simplejson 2.0.x - Code Review (original) (raw)
OLD
NEW
1 """Implementation of JSONEncoder
1 """Implementation of JSONEncoder
2 """
2 """
3
4 import re
3 import re
5 import math
6
4
7 try:
5 try:
8 from _json import encode_basestring_ascii as c_encode_basestring_ascii
6 from _json import encode_basestring_ascii as c_encode_basestring_ascii
9 except ImportError:
7 except ImportError:
10 c_encode_basestring_ascii = None
8 c_encode_basestring_ascii = None
11
9 try:
12 __all__ = ['JSONEncoder']
10 from _json import make_encoder as c_make_encoder
11 except ImportError:
12 c_make_encoder = None
13
13
14 ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
14 ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
15 ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
15 ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
16 HAS_UTF8 = re.compile(r'[\x80-\xff]')
16 HAS_UTF8 = re.compile(r'[\x80-\xff]')
17 ESCAPE_DCT = {
17 ESCAPE_DCT = {
18 '\\': '\\\\',
18 '\\': '\\\\',
19 '"': '\\"',
19 '"': '\\"',
20 '\b': '\\b',
20 '\b': '\\b',
21 '\f': '\\f',
21 '\f': '\\f',
22 '\n': '\\n',
22 '\n': '\\n',
23 '\r': '\\r',
23 '\r': '\\r',
24 '\t': '\\t',
24 '\t': '\\t',
25 }
25 }
26 for i in range(0x20):
26 for i in range(0x20):
27 ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
27 ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
28 #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
28
29
30 # Assume this produces an infinity on all machines (probably not guaranteed)
31 INFINITY = float('1e66666')
29 FLOAT_REPR = repr
32 FLOAT_REPR = repr
30
33
31 def floatstr(o, allow_nan=True):
32 # Check for specials. Note that this type of test is processor- and/or
33 # platform-specific, so do tests which don't depend on the internals.
34
35 if math.isnan(o):
36 text = 'NaN'
37 elif math.isinf(o):
38 if math.copysign(1., o) == 1.:
39 text = 'Infinity'
40 else:
41 text = '-Infinity'
42 else:
43 return FLOAT_REPR(o)
44
45 if not allow_nan:
46 msg = "Out of range float values are not JSON compliant: " + repr(o)
47 raise ValueError(msg)
48
49 return text
50
51
52 def encode_basestring(s):
34 def encode_basestring(s):
53 """Return a JSON representation of a Python string
35 """Return a JSON representation of a Python string
54
36
55 """
37 """
56 def replace(match):
38 def replace(match):
57 return ESCAPE_DCT[match.group(0)]
39 return ESCAPE_DCT[match.group(0)]
58 return '"' + ESCAPE.sub(replace, s) + '"'
40 return '"' + ESCAPE.sub(replace, s) + '"'
59
41
60
42
61 def py_encode_basestring_ascii(s):
43 def py_encode_basestring_ascii(s):
44 """Return an ASCII-only JSON representation of a Python string
45
46 """
62 if isinstance(s, str) and HAS_UTF8.search(s) is not None:
47 if isinstance(s, str) and HAS_UTF8.search(s) is not None:
63 s = s.decode('utf-8')
48 s = s.decode('utf-8')
64 def replace(match):
49 def replace(match):
65 s = match.group(0)
50 s = match.group(0)
66 try:
51 try:
67 return ESCAPE_DCT[s]
52 return ESCAPE_DCT[s]
68 except KeyError:
53 except KeyError:
69 n = ord(s)
54 n = ord(s)
70 if n < 0x10000:
55 if n < 0x10000:
71 return '\\u{0:04x}'.format(n)
56 return '\\u{0:04x}'.format(n)
57 #return '\\u%04x' % (n,)
72 else:
58 else:
73 # surrogate pair
59 # surrogate pair
74 n -= 0x10000
60 n -= 0x10000
75 s1 = 0xd800 | ((n >> 10) & 0x3ff)
61 s1 = 0xd800 | ((n >> 10) & 0x3ff)
76 s2 = 0xdc00 | (n & 0x3ff)
62 s2 = 0xdc00 | (n & 0x3ff)
77 return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
63 return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
64 #return '\\u%04x\\u%04x' % (s1, s2)
78 return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
65 return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
79
66
80
67
81 if c_encode_basestring_ascii is not None:
68 encode_basestring_ascii = (
82 encode_basestring_ascii = c_encode_basestring_ascii
69 c_encode_basestring_ascii or py_encode_basestring_ascii)
83 else:
84 encode_basestring_ascii = py_encode_basestring_ascii
85
86
70
87 class JSONEncoder(object):
71 class JSONEncoder(object):
88 """Extensible JSON http://json.org encoder for Python data structures.
72 """Extensible JSON http://json.org encoder for Python data structures.
89
73
90 Supports the following objects and types by default:
74 Supports the following objects and types by default:
91
75
92 +-------------------+---------------+
76 +-------------------+---------------+
93 | Python | JSON |
77 | Python | JSON |
94 +===================+===============+
78 +===================+===============+
95 | dict | object |
79 | dict | object |
(...skipping 10 matching lines...) Expand all Loading...
106 +-------------------+---------------+
90 +-------------------+---------------+
107 | None | null |
91 | None | null |
108 +-------------------+---------------+
92 +-------------------+---------------+
109
93
110 To extend this to recognize other objects, subclass and implement a
94 To extend this to recognize other objects, subclass and implement a
111 ``.default()`` method with another method that returns a serializable
95 ``.default()`` method with another method that returns a serializable
112 object for ``o`` if possible, otherwise it should call the superclass
96 object for ``o`` if possible, otherwise it should call the superclass
113 implementation (to raise ``TypeError``).
97 implementation (to raise ``TypeError``).
114
98
115 """
99 """
116 __all__ = ['__init__', 'default', 'encode', 'iterencode']
117 item_separator = ', '
100 item_separator = ', '
118 key_separator = ': '
101 key_separator = ': '
119 def __init__(self, skipkeys=False, ensure_ascii=True,
102 def __init__(self, skipkeys=False, ensure_ascii=True,
120 check_circular=True, allow_nan=True, sort_keys=False,
103 check_circular=True, allow_nan=True, sort_keys=False,
121 indent=None, separators=None, encoding='utf-8', default=None):
104 indent=None, separators=None, encoding='utf-8', default=None):
122 """Constructor for JSONEncoder, with sensible defaults.
105 """Constructor for JSONEncoder, with sensible defaults.
123
106
124 If skipkeys is False, then it is a TypeError to attempt
107 If skipkeys is false, then it is a TypeError to attempt
125 encoding of keys that are not str, int, long, float or None. If
108 encoding of keys that are not str, int, long, float or None. If
126 skipkeys is True, such items are simply skipped.
109 skipkeys is True, such items are simply skipped.
127
110
128 If ensure_ascii is True, the output is guaranteed to be str
111 If ensure_ascii is true, the output is guaranteed to be str
129 objects with all incoming unicode characters escaped. If
112 objects with all incoming unicode characters escaped. If
130 ensure_ascii is false, the output will be unicode object.
113 ensure_ascii is false, the output will be unicode object.
131
114
132 If check_circular is True, then lists, dicts, and custom encoded
115 If check_circular is true, then lists, dicts, and custom encoded
133 objects will be checked for circular references during encoding to
116 objects will be checked for circular references during encoding to
134 prevent an infinite recursion (which would cause an OverflowError).
117 prevent an infinite recursion (which would cause an OverflowError).
135 Otherwise, no such check takes place.
118 Otherwise, no such check takes place.
136
119
137 If allow_nan is True, then NaN, Infinity, and -Infinity will be
120 If allow_nan is true, then NaN, Infinity, and -Infinity will be
138 encoded as such. This behavior is not JSON specification compliant,
121 encoded as such. This behavior is not JSON specification compliant,
139 but is consistent with most JavaScript based encoders and decoders.
122 but is consistent with most JavaScript based encoders and decoders.
140 Otherwise, it will be a ValueError to encode such floats.
123 Otherwise, it will be a ValueError to encode such floats.
141
124
142 If sort_keys is True, then the output of dictionaries will be
125 If sort_keys is true, then the output of dictionaries will be
143 sorted by key; this is useful for regression tests to ensure
126 sorted by key; this is useful for regression tests to ensure
144 that JSON serializations can be compared on a day-to-day basis.
127 that JSON serializations can be compared on a day-to-day basis.
145
128
146 If indent is a non-negative integer, then JSON array
129 If indent is a non-negative integer, then JSON array
147 elements and object members will be pretty-printed with that
130 elements and object members will be pretty-printed with that
148 indent level. An indent level of 0 will only insert newlines.
131 indent level. An indent level of 0 will only insert newlines.
149 None is the most compact representation.
132 None is the most compact representation.
150
133
151 If specified, separators should be a (item_separator, key_separator)
134 If specified, separators should be a (item_separator, key_separator)
152 tuple. The default is (', ', ': '). To get the most compact JSON
135 tuple. The default is (', ', ': '). To get the most compact JSON
153 representation you should specify (',', ':') to eliminate whitespace.
136 representation you should specify (',', ':') to eliminate whitespace.
154
137
155 If specified, default is a function that gets called for objects
138 If specified, default is a function that gets called for objects
156 that can't otherwise be serialized. It should return a JSON encodable
139 that can't otherwise be serialized. It should return a JSON encodable
157 version of the object or raise a ``TypeError``.
140 version of the object or raise a ``TypeError``.
158
141
159 If encoding is not None, then all input strings will be
142 If encoding is not None, then all input strings will be
160 transformed into unicode using that encoding prior to JSON-encoding.
143 transformed into unicode using that encoding prior to JSON-encoding.
161 The default is UTF-8.
144 The default is UTF-8.
162
145
163 """
146 """
147
164 self.skipkeys = skipkeys
148 self.skipkeys = skipkeys
165 self.ensure_ascii = ensure_ascii
149 self.ensure_ascii = ensure_ascii
166 self.check_circular = check_circular
150 self.check_circular = check_circular
167 self.allow_nan = allow_nan
151 self.allow_nan = allow_nan
168 self.sort_keys = sort_keys
152 self.sort_keys = sort_keys
169 self.indent = indent
153 self.indent = indent
170 self.current_indent_level = 0
171 if separators is not None:
154 if separators is not None:
172 self.item_separator, self.key_separator = separators
155 self.item_separator, self.key_separator = separators
173 if default is not None:
156 if default is not None:
174 self.default = default
157 self.default = default
175 self.encoding = encoding
158 self.encoding = encoding
176
159
177 def _newline_indent(self):
160 def default(self, o):
178 return '\n' + (' ' * (self.indent * self.current_indent_level))
161 """Implement this method in a subclass such that it returns
162 a serializable object for ``o``, or calls the base implementation
163 (to raise a ``TypeError``).
179
164
180 def _iterencode_list(self, lst, markers=None):
165 For example, to support arbitrary iterators, you could
166 implement default like this::
167
168 def default(self, o):
169 try:
170 iterable = iter(o)
171 except TypeError:
172 pass
173 else:
174 return list(iterable)
175 return JSONEncoder.default(self, o)
176
177 """
178 raise TypeError(repr(o) + " is not JSON serializable")
179
180 def encode(self, o):
181 """Return a JSON string representation of a Python data structure.
182
183 >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
184 '{"foo": ["bar", "baz"]}'
185
186 """
187 # This is for extremely simple cases and benchmarks.
188 if isinstance(o, basestring):
189 if isinstance(o, str):
190 _encoding = self.encoding
191 if (_encoding is not None
192 and not (_encoding == 'utf-8')):
193 o = o.decode(_encoding)
194 if self.ensure_ascii:
195 return encode_basestring_ascii(o)
196 else:
197 return encode_basestring(o)
198 # This doesn't pass the iterator directly to ''.join() because the
199 # exceptions aren't as detailed. The list call should be roughly
200 # equivalent to the PySequence_Fast that ''.join() would do.
201 chunks = self.iterencode(o, _one_shot=True)
202 if not isinstance(chunks, (list, tuple)):
203 chunks = list(chunks)
204 return ''.join(chunks)
205
206 def iterencode(self, o, _one_shot=False):
207 """Encode the given object and yield each string
208 representation as available.
209
210 For example::
211
212 for chunk in JSONEncoder().iterencode(bigobject):
213 mysocket.write(chunk)
214
215 """
216 if self.check_circular:
217 markers = {}
218 else:
219 markers = None
220 if self.ensure_ascii:
221 _encoder = encode_basestring_ascii
222 else:
223 _encoder = encode_basestring
224 if self.encoding != 'utf-8':
225 def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
226 if isinstance(o, str):
227 o = o.decode(_encoding)
228 return _orig_encoder(o)
229
230 def floatstr(o, allow_nan=self.allow_nan,
231 _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY):
232 # Check for specials. Note that this type of test is processor
233 # and/or platform-specific, so do tests which don't depend on the
234 # internals.
235
236 if o != o:
237 text = 'NaN'
238 elif o == _inf:
239 text = 'Infinity'
240 elif o == _neginf:
241 text = '-Infinity'
242 else:
243 return _repr(o)
244
245 if not allow_nan:
246 raise ValueError(
247 "Out of range float values are not JSON compliant: " +
248 repr(o))
249
250 return text
251
252
253 if (_one_shot and c_make_encoder is not None
254 and not self.indent and not self.sort_keys):
255 _iterencode = c_make_encoder(
256 markers, self.default, _encoder, self.indent,
257 self.key_separator, self.item_separator, self.sort_keys,
258 self.skipkeys, self.allow_nan)
259 else:
260 _iterencode = _make_iterencode(
261 markers, self.default, _encoder, self.indent, floatstr,
262 self.key_separator, self.item_separator, self.sort_keys,
263 self.skipkeys, _one_shot)
264 return _iterencode(o, 0)
265
266 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
267 _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
268 ## HACK: hand-optimized bytecode; turn globals into locals
269 False=False,
270 True=True,
271 ValueError=ValueError,
272 basestring=basestring,
273 dict=dict,
274 float=float,
275 id=id,
276 int=int,
277 isinstance=isinstance,
278 list=list,
279 long=long,
280 str=str,
281 tuple=tuple,
282 ):
283
284 def _iterencode_list(lst, _current_indent_level):
181 if not lst:
285 if not lst:
182 yield '[]'
286 yield '[]'
183 return
287 return
184 if markers is not None:
288 if markers is not None:
185 markerid = id(lst)
289 markerid = id(lst)
186 if markerid in markers:
290 if markerid in markers:
187 raise ValueError("Circular reference detected")
291 raise ValueError("Circular reference detected")
188 markers[markerid] = lst
292 markers[markerid] = lst
189 yield '['
293 buf = '['
190 if self.indent is not None:
294 if _indent is not None:
191 self.current_indent_level += 1
295 _current_indent_level += 1
192 newline_indent = self._newline_indent()
296 newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
193 separator = self.item_separator + newline_indent
297 separator = _item_separator + newline_indent
194 yield newline_indent
298 buf += newline_indent
195 else:
299 else:
196 newline_indent = None
300 newline_indent = None
197 separator = self.item_separator
301 separator = _item_separator
198 first = True
302 first = True
199 for value in lst:
303 for value in lst:
200 if first:
304 if first:
201 first = False
305 first = False
202 else:
306 else:
203 yield separator
307 buf = separator
204 for chunk in self._iterencode(value, markers):
308 if isinstance(value, basestring):
205 yield chunk
309 yield buf + _encoder(value)
310 elif value is None:
311 yield buf + 'null'
312 elif value is True:
313 yield buf + 'true'
314 elif value is False:
315 yield buf + 'false'
316 elif isinstance(value, (int, long)):
317 yield buf + str(value)
318 elif isinstance(value, float):
319 yield buf + _floatstr(value)
320 else:
321 yield buf
322 if isinstance(value, (list, tuple)):
323 chunks = _iterencode_list(value, _current_indent_level)
324 elif isinstance(value, dict):
325 chunks = _iterencode_dict(value, _current_indent_level)
326 else:
327 chunks = _iterencode(value, _current_indent_level)
328 for chunk in chunks:
329 yield chunk
206 if newline_indent is not None:
330 if newline_indent is not None:
207 self.current_indent_level -= 1
331 _current_indent_level -= 1
208 yield self._newline_indent()
332 yield '\n' + (' ' * (_indent * _current_indent_level))
209 yield ']'
333 yield ']'
210 if markers is not None:
334 if markers is not None:
211 del markers[markerid]
335 del markers[markerid]
212
336
213 def _iterencode_dict(self, dct, markers=None):
337 def _iterencode_dict(dct, _current_indent_level):
214 if not dct:
338 if not dct:
215 yield '{}'
339 yield '{}'
216 return
340 return
217 if markers is not None:
341 if markers is not None:
218 markerid = id(dct)
342 markerid = id(dct)
219 if markerid in markers:
343 if markerid in markers:
220 raise ValueError("Circular reference detected")
344 raise ValueError("Circular reference detected")
221 markers[markerid] = dct
345 markers[markerid] = dct
222 yield '{'
346 yield '{'
223 key_separator = self.key_separator
347 if _indent is not None:
224 if self.indent is not None:
348 _current_indent_level += 1
225 self.current_indent_level += 1
349 newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
226 newline_indent = self._newline_indent()
350 item_separator = _item_separator + newline_indent
227 item_separator = self.item_separator + newline_indent
228 yield newline_indent
351 yield newline_indent
229 else:
352 else:
230 newline_indent = None
353 newline_indent = None
231 item_separator = self.item_separator
354 item_separator = _item_separator
232 first = True
355 first = True
233 if self.ensure_ascii:
356 if _sort_keys:
234 encoder = encode_basestring_ascii
357 items = dct.items()
235 else:
358 items.sort(key=lambda kv: kv[0])
236 encoder = encode_basestring
237 allow_nan = self.allow_nan
238 if self.sort_keys:
239 keys = dct.keys()
240 keys.sort()
241 items = [(k, dct[k]) for k in keys]
242 else:
359 else:
243 items = dct.iteritems()
360 items = dct.iteritems()
244 _encoding = self.encoding
245 _do_decode = (_encoding is not None
246 and not (_encoding == 'utf-8'))
247 for key, value in items:
361 for key, value in items:
248 if isinstance(key, str):
362 if isinstance(key, basestring):
249 if _do_decode:
250 key = key.decode(_encoding)
251 elif isinstance(key, basestring):
252 pass
363 pass
253 # JavaScript is weakly typed for these, so it makes sense to
364 # JavaScript is weakly typed for these, so it makes sense to
254 # also allow them. Many encoders seem to do something like this.
365 # also allow them. Many encoders seem to do something like this.
255 elif isinstance(key, float):
366 elif isinstance(key, float):
256 key = floatstr(key, allow_nan)
367 key = _floatstr(key)
257 elif isinstance(key, (int, long)):
258 key = str(key)
259 elif key is True:
368 elif key is True:
260 key = 'true'
369 key = 'true'
261 elif key is False:
370 elif key is False:
262 key = 'false'
371 key = 'false'
263 elif key is None:
372 elif key is None:
264 key = 'null'
373 key = 'null'
265 elif self.skipkeys:
374 elif isinstance(key, (int, long)):
375 key = str(key)
376 elif _skipkeys:
266 continue
377 continue
267 else:
378 else:
268 raise TypeError("key {0!r} is not a string".format(key))
379 raise TypeError("key " + repr(key) + " is not a string")
269 if first:
380 if first:
270 first = False
381 first = False
271 else:
382 else:
272 yield item_separator
383 yield item_separator
273 yield encoder(key)
384 yield _encoder(key)
274 yield key_separator
385 yield _key_separator
275 for chunk in self._iterencode(value, markers):
386 if isinstance(value, basestring):
276 yield chunk
387 yield _encoder(value)
388 elif value is None:
389 yield 'null'
390 elif value is True:
391 yield 'true'
392 elif value is False:
393 yield 'false'
394 elif isinstance(value, (int, long)):
395 yield str(value)
396 elif isinstance(value, float):
397 yield _floatstr(value)
398 else:
399 if isinstance(value, (list, tuple)):
400 chunks = _iterencode_list(value, _current_indent_level)
401 elif isinstance(value, dict):
402 chunks = _iterencode_dict(value, _current_indent_level)
403 else:
404 chunks = _iterencode(value, _current_indent_level)
405 for chunk in chunks:
406 yield chunk
277 if newline_indent is not None:
407 if newline_indent is not None:
278 self.current_indent_level -= 1
408 _current_indent_level -= 1
279 yield self._newline_indent()
409 yield '\n' + (' ' * (_indent * _current_indent_level))
280 yield '}'
410 yield '}'
281 if markers is not None:
411 if markers is not None:
282 del markers[markerid]
412 del markers[markerid]
283
413
284 def _iterencode(self, o, markers=None):
414 def _iterencode(o, _current_indent_level):
285 if isinstance(o, basestring):
415 if isinstance(o, basestring):
286 if self.ensure_ascii:
416 yield _encoder(o)
287 encoder = encode_basestring_ascii
288 else:
289 encoder = encode_basestring
290 _encoding = self.encoding
291 if (_encoding is not None and isinstance(o, str)
292 and not (_encoding == 'utf-8')):
293 o = o.decode(_encoding)
294 yield encoder(o)
295 elif o is None:
417 elif o is None:
296 yield 'null'
418 yield 'null'
297 elif o is True:
419 elif o is True:
298 yield 'true'
420 yield 'true'
299 elif o is False:
421 elif o is False:
300 yield 'false'
422 yield 'false'
301 elif isinstance(o, (int, long)):
423 elif isinstance(o, (int, long)):
302 yield str(o)
424 yield str(o)
303 elif isinstance(o, float):
425 elif isinstance(o, float):
304 yield floatstr(o, self.allow_nan)
426 yield _floatstr(o)
305 elif isinstance(o, (list, tuple)):
427 elif isinstance(o, (list, tuple)):
306 for chunk in self._iterencode_list(o, markers):
428 for chunk in _iterencode_list(o, _current_indent_level):
307 yield chunk
429 yield chunk
308 elif isinstance(o, dict):
430 elif isinstance(o, dict):
309 for chunk in self._iterencode_dict(o, markers):
431 for chunk in _iterencode_dict(o, _current_indent_level):
310 yield chunk
432 yield chunk
311 else:
433 else:
312 if markers is not None:
434 if markers is not None:
313 markerid = id(o)
435 markerid = id(o)
314 if markerid in markers:
436 if markerid in markers:
315 raise ValueError("Circular reference detected")
437 raise ValueError("Circular reference detected")
316 markers[markerid] = o
438 markers[markerid] = o
317 for chunk in self._iterencode_default(o, markers):
439 o = _default(o)
440 for chunk in _iterencode(o, _current_indent_level):
318 yield chunk
441 yield chunk
319 if markers is not None:
442 if markers is not None:
320 del markers[markerid]
443 del markers[markerid]
321
444
322 def _iterencode_default(self, o, markers=None):
445 return _iterencode
323 newobj = self.default(o)
324 return self._iterencode(newobj, markers)
325
326 def default(self, o):
327 """Implement this method in a subclass such that it returns a serializab le
328 object for ``o``, or calls the base implementation (to raise a
329 ``TypeError``).
330
331 For example, to support arbitrary iterators, you could implement
332 default like this::
333
334 def default(self, o):
335 try:
336 iterable = iter(o)
337 except TypeError:
338 pass
339 else:
340 return list(iterable)
341 return JSONEncoder.default(self, o)
342
343 """
344 raise TypeError(repr(o) + " is not JSON serializable")
345
346 def encode(self, o):
347 """Return a JSON string representation of a Python data structure.
348
349 >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
350 '{"foo": ["bar", "baz"]}'
351
352 """
353 # This is for extremely simple cases and benchmarks.
354 if isinstance(o, basestring):
355 if isinstance(o, str):
356 _encoding = self.encoding
357 if (_encoding is not None
358 and not (_encoding == 'utf-8')):
359 o = o.decode(_encoding)
360 if self.ensure_ascii:
361 return encode_basestring_ascii(o)
362 else:
363 return encode_basestring(o)
364 # This doesn't pass the iterator directly to ''.join() because the
365 # exceptions aren't as detailed. The list call should be roughly
366 # equivalent to the PySequence_Fast that ''.join() would do.
367 chunks = list(self.iterencode(o))
368 return ''.join(chunks)
369
370 def iterencode(self, o):
371 """Encode the given object and yield each string representation as
372 available.
373
374 For example::
375
376 for chunk in JSONEncoder().iterencode(bigobject):
377 mysocket.write(chunk)
378
379 """
380 if self.check_circular:
381 markers = {}
382 else:
383 markers = None
384 return self._iterencode(o, markers)
OLD
NEW