[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