Changeset 391 for python/trunk/Lib/json
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 22 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/json/__init__.py
r2 r391 1 r"""A simple, fast, extensible JSON encoder and decoder 2 3 JSON (JavaScript Object Notation) <http://json.org> is a subset of 1 r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of 4 2 JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data 5 3 interchange format. 6 4 7 json exposes an API familiar to uses of the standard library 8 marshal and pickle modules. 5 :mod:`json` exposes an API familiar to users of the standard library 6 :mod:`marshal` and :mod:`pickle` modules. It is the externally maintained 7 version of the :mod:`json` library contained in Python 2.6, but maintains 8 compatibility with Python 2.4 and Python 2.5 and (currently) has 9 significant performance advantages, even without using the optional C 10 extension for speedups. 9 11 10 12 Encoding basic Python object hierarchies:: … … 30 32 31 33 >>> import json 32 >>> json.dumps([1,2,3,{'4': 5, '6': 7}], s eparators=(',',':'))34 >>> json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=(',',':')) 33 35 '[1,2,3,{"4":5,"6":7}]' 34 36 35 Pretty printing (using repr() because of extraneous whitespace in the output):: 36 37 >>> import json 38 >>> print repr(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)) 39 '{\n "4": 5, \n "6": 7\n}' 37 Pretty printing:: 38 39 >>> import json 40 >>> print json.dumps({'4': 5, '6': 7}, sort_keys=True, 41 ... indent=4, separators=(',', ': ')) 42 { 43 "4": 5, 44 "6": 7 45 } 40 46 41 47 Decoding JSON:: 42 48 43 49 >>> import json 44 >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') 45 [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] 46 >>> json.loads('"\\"foo\\bar"') 47 u'"foo\x08ar' 50 >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] 51 >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj 52 True 53 >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar' 54 True 48 55 >>> from StringIO import StringIO 49 56 >>> io = StringIO('["streaming API"]') 50 >>> json.load(io) 51 [u'streaming API']57 >>> json.load(io)[0] == 'streaming API' 58 True 52 59 53 60 Specializing JSON object decoding:: … … 62 69 ... object_hook=as_complex) 63 70 (1+2j) 64 >>> import decimal 65 >>> json.loads('1.1', parse_float=decimal.Decimal) 66 Decimal('1.1') 67 68 Extending JSONEncoder:: 69 70 >>> import json 71 >>> class ComplexEncoder(json.JSONEncoder): 72 ... def default(self, obj): 73 ... if isinstance(obj, complex): 74 ... return [obj.real, obj.imag] 75 ... return json.JSONEncoder.default(self, obj) 71 >>> from decimal import Decimal 72 >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1') 73 True 74 75 Specializing JSON object encoding:: 76 77 >>> import json 78 >>> def encode_complex(obj): 79 ... if isinstance(obj, complex): 80 ... return [obj.real, obj.imag] 81 ... raise TypeError(repr(o) + " is not JSON serializable") 76 82 ... 77 >>> dumps(2 + 1j, cls=ComplexEncoder)83 >>> json.dumps(2 + 1j, default=encode_complex) 78 84 '[2.0, 1.0]' 79 >>> ComplexEncoder().encode(2 + 1j)85 >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j) 80 86 '[2.0, 1.0]' 81 >>> list(ComplexEncoder().iterencode(2 + 1j)) 82 ['[', '2.0', ', ', '1.0', ']'] 83 84 85 Using json.tool from the shell to validate and 86 pretty-print:: 87 88 $ echo '{"json":"obj"}' | python -mjson.tool 87 >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j)) 88 '[2.0, 1.0]' 89 90 91 Using json.tool from the shell to validate and pretty-print:: 92 93 $ echo '{"json":"obj"}' | python -m json.tool 89 94 { 90 95 "json": "obj" 91 96 } 92 $ echo '{ 1.2:3.4}' | python -mjson.tool 93 Expecting property name: line 1 column 2 (char 2) 94 95 Note that the JSON produced by this module's default settings 96 is a subset of YAML, so it may be used as a serializer for that as well. 97 97 $ echo '{ 1.2:3.4}' | python -m json.tool 98 Expecting property name enclosed in double quotes: line 1 column 3 (char 2) 98 99 """ 99 100 __version__ = '1.9' 100 __version__ = '2.0.9' 101 101 __all__ = [ 102 102 'dump', 'dumps', 'load', 'loads', … … 122 122 def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, 123 123 allow_nan=True, cls=None, indent=None, separators=None, 124 encoding='utf-8', default=None, **kw):124 encoding='utf-8', default=None, sort_keys=False, **kw): 125 125 """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a 126 126 ``.write()``-supporting file-like object). 127 127 128 If ``skipkeys`` is ``True``then ``dict`` keys that are not basic types128 If ``skipkeys`` is true then ``dict`` keys that are not basic types 129 129 (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 130 130 will be skipped instead of raising a ``TypeError``. 131 131 132 If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp`` 133 may be ``unicode`` instances, subject to normal Python ``str`` to 134 ``unicode`` coercion rules. Unless ``fp.write()`` explicitly 135 understands ``unicode`` (as in ``codecs.getwriter()``) this is likely 136 to cause an error. 137 138 If ``check_circular`` is ``False``, then the circular reference check 132 If ``ensure_ascii`` is true (the default), all non-ASCII characters in the 133 output are escaped with ``\uXXXX`` sequences, and the result is a ``str`` 134 instance consisting of ASCII characters only. If ``ensure_ascii`` is 135 ``False``, some chunks written to ``fp`` may be ``unicode`` instances. 136 This usually happens because the input contains unicode strings or the 137 ``encoding`` parameter is used. Unless ``fp.write()`` explicitly 138 understands ``unicode`` (as in ``codecs.getwriter``) this is likely to 139 cause an error. 140 141 If ``check_circular`` is false, then the circular reference check 139 142 for container types will be skipped and a circular reference will 140 143 result in an ``OverflowError`` (or worse). 141 144 142 If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to145 If ``allow_nan`` is false, then it will be a ``ValueError`` to 143 146 serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) 144 147 in strict compliance of the JSON specification, instead of using the 145 148 JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). 146 149 147 If ``indent`` is a non-negative integer, then JSON array elements and object 148 members will be pretty-printed with that indent level. An indent level 149 of 0 will only insert newlines. ``None`` is the most compact representation. 150 If ``indent`` is a non-negative integer, then JSON array elements and 151 object members will be pretty-printed with that indent level. An indent 152 level of 0 will only insert newlines. ``None`` is the most compact 153 representation. Since the default item separator is ``', '``, the 154 output might include trailing whitespace when ``indent`` is specified. 155 You can use ``separators=(',', ': ')`` to avoid this. 150 156 151 157 If ``separators`` is an ``(item_separator, dict_separator)`` tuple … … 158 164 of obj or raise TypeError. The default simply raises TypeError. 159 165 166 If *sort_keys* is ``True`` (default: ``False``), then the output of 167 dictionaries will be sorted by key. 168 160 169 To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the 161 170 ``.default()`` method to serialize additional types), specify it with 162 the ``cls`` kwarg .171 the ``cls`` kwarg; otherwise ``JSONEncoder`` is used. 163 172 164 173 """ 165 174 # cached encoder 166 if ( skipkeys is False and ensure_ascii is Trueand167 check_circular is True and allow_nan is Trueand175 if (not skipkeys and ensure_ascii and 176 check_circular and allow_nan and 168 177 cls is None and indent is None and separators is None and 169 encoding == 'utf-8' and default is None and not kw):178 encoding == 'utf-8' and default is None and not sort_keys and not kw): 170 179 iterable = _default_encoder.iterencode(obj) 171 180 else: … … 175 184 check_circular=check_circular, allow_nan=allow_nan, indent=indent, 176 185 separators=separators, encoding=encoding, 177 default=default, **kw).iterencode(obj)186 default=default, sort_keys=sort_keys, **kw).iterencode(obj) 178 187 # could accelerate with writelines in some versions of Python, at 179 188 # a debuggability cost … … 184 193 def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, 185 194 allow_nan=True, cls=None, indent=None, separators=None, 186 encoding='utf-8', default=None, **kw):195 encoding='utf-8', default=None, sort_keys=False, **kw): 187 196 """Serialize ``obj`` to a JSON formatted ``str``. 188 197 189 If ``skipkeys`` is ``True``then ``dict`` keys that are not basic types198 If ``skipkeys`` is false then ``dict`` keys that are not basic types 190 199 (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 191 200 will be skipped instead of raising a ``TypeError``. 192 201 193 If ``ensure_ascii`` is ``False``, then the return value will be a 194 ``unicode`` instance subject to normal Python ``str`` to ``unicode`` 195 coercion rules instead of being escaped to an ASCII ``str``. 196 197 If ``check_circular`` is ``False``, then the circular reference check 202 If ``ensure_ascii`` is false, all non-ASCII characters are not escaped, and 203 the return value may be a ``unicode`` instance. See ``dump`` for details. 204 205 If ``check_circular`` is false, then the circular reference check 198 206 for container types will be skipped and a circular reference will 199 207 result in an ``OverflowError`` (or worse). 200 208 201 If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to209 If ``allow_nan`` is false, then it will be a ``ValueError`` to 202 210 serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in 203 211 strict compliance of the JSON specification, instead of using the … … 207 215 object members will be pretty-printed with that indent level. An indent 208 216 level of 0 will only insert newlines. ``None`` is the most compact 209 representation. 217 representation. Since the default item separator is ``', '``, the 218 output might include trailing whitespace when ``indent`` is specified. 219 You can use ``separators=(',', ': ')`` to avoid this. 210 220 211 221 If ``separators`` is an ``(item_separator, dict_separator)`` tuple … … 218 228 of obj or raise TypeError. The default simply raises TypeError. 219 229 230 If *sort_keys* is ``True`` (default: ``False``), then the output of 231 dictionaries will be sorted by key. 232 220 233 To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the 221 234 ``.default()`` method to serialize additional types), specify it with 222 the ``cls`` kwarg .235 the ``cls`` kwarg; otherwise ``JSONEncoder`` is used. 223 236 224 237 """ 225 238 # cached encoder 226 if ( skipkeys is False and ensure_ascii is Trueand227 check_circular is True and allow_nan is Trueand239 if (not skipkeys and ensure_ascii and 240 check_circular and allow_nan and 228 241 cls is None and indent is None and separators is None and 229 encoding == 'utf-8' and default is None and not kw):242 encoding == 'utf-8' and default is None and not sort_keys and not kw): 230 243 return _default_encoder.encode(obj) 231 244 if cls is None: … … 235 248 check_circular=check_circular, allow_nan=allow_nan, indent=indent, 236 249 separators=separators, encoding=encoding, default=default, 237 **kw).encode(obj) 238 239 240 _default_decoder = JSONDecoder(encoding=None, object_hook=None) 250 sort_keys=sort_keys, **kw).encode(obj) 251 252 253 _default_decoder = JSONDecoder(encoding=None, object_hook=None, 254 object_pairs_hook=None) 241 255 242 256 243 257 def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, 244 parse_int=None, parse_constant=None, **kw):245 """Deserialize ``fp`` (a ``.read()``-supporting file-like object 246 containinga JSON document) to a Python object.258 parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): 259 """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing 260 a JSON document) to a Python object. 247 261 248 262 If the contents of ``fp`` is encoded with an ASCII based encoding other … … 258 272 can be used to implement custom decoders (e.g. JSON-RPC class hinting). 259 273 274 ``object_pairs_hook`` is an optional function that will be called with the 275 result of any object literal decoded with an ordered list of pairs. The 276 return value of ``object_pairs_hook`` will be used instead of the ``dict``. 277 This feature can be used to implement custom decoders that rely on the 278 order that the key and value pairs are decoded (for example, 279 collections.OrderedDict will remember the order of insertion). If 280 ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority. 281 260 282 To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` 261 kwarg .283 kwarg; otherwise ``JSONDecoder`` is used. 262 284 263 285 """ … … 265 287 encoding=encoding, cls=cls, object_hook=object_hook, 266 288 parse_float=parse_float, parse_int=parse_int, 267 parse_constant=parse_constant, **kw) 289 parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, 290 **kw) 268 291 269 292 270 293 def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, 271 parse_int=None, parse_constant=None, **kw):294 parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): 272 295 """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON 273 296 document) to a Python object. … … 283 306 can be used to implement custom decoders (e.g. JSON-RPC class hinting). 284 307 308 ``object_pairs_hook`` is an optional function that will be called with the 309 result of any object literal decoded with an ordered list of pairs. The 310 return value of ``object_pairs_hook`` will be used instead of the ``dict``. 311 This feature can be used to implement custom decoders that rely on the 312 order that the key and value pairs are decoded (for example, 313 collections.OrderedDict will remember the order of insertion). If 314 ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority. 315 285 316 ``parse_float``, if specified, will be called with the string 286 317 of every JSON float to be decoded. By default this is equivalent to … … 299 330 300 331 To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` 301 kwarg .332 kwarg; otherwise ``JSONDecoder`` is used. 302 333 303 334 """ 304 335 if (cls is None and encoding is None and object_hook is None and 305 336 parse_int is None and parse_float is None and 306 parse_constant is None and not kw):337 parse_constant is None and object_pairs_hook is None and not kw): 307 338 return _default_decoder.decode(s) 308 339 if cls is None: … … 310 341 if object_hook is not None: 311 342 kw['object_hook'] = object_hook 343 if object_pairs_hook is not None: 344 kw['object_pairs_hook'] = object_pairs_hook 312 345 if parse_float is not None: 313 346 kw['parse_float'] = parse_float -
python/trunk/Lib/json/decoder.py
r2 r391 1 1 """Implementation of JSONDecoder 2 2 """ 3 4 3 import re 5 4 import sys 6 7 from json.scanner import Scanner, pattern 5 import struct 6 7 from json import scanner 8 8 try: 9 9 from _json import scanstring as c_scanstring … … 15 15 FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL 16 16 17 NaN, PosInf, NegInf = float('nan'), float('inf'), float('-inf') 17 def _floatconstants(): 18 _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') 19 if sys.byteorder != 'big': 20 _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1] 21 nan, inf = struct.unpack('dd', _BYTES) 22 return nan, inf, -inf 23 24 NaN, PosInf, NegInf = _floatconstants() 18 25 19 26 … … 21 28 lineno = doc.count('\n', 0, pos) + 1 22 29 if lineno == 1: 23 colno = pos 30 colno = pos + 1 24 31 else: 25 32 colno = pos - doc.rindex('\n', 0, pos) … … 28 35 29 36 def errmsg(msg, doc, pos, end=None): 37 # Note that this function is called from _json 30 38 lineno, colno = linecol(doc, pos) 31 39 if end is None: 32 40 fmt = '{0}: line {1} column {2} (char {3})' 33 41 return fmt.format(msg, lineno, colno, pos) 42 #fmt = '%s: line %d column %d (char %d)' 43 #return fmt % (msg, lineno, colno, pos) 34 44 endlineno, endcolno = linecol(doc, end) 35 45 fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})' 36 46 return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end) 47 #fmt = '%s: line %d column %d - line %d column %d (char %d - %d)' 48 #return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end) 37 49 38 50 … … 41 53 'Infinity': PosInf, 42 54 'NaN': NaN, 43 'true': True,44 'false': False,45 'null': None,46 55 } 47 48 49 def JSONConstant(match, context, c=_CONSTANTS):50 s = match.group(0)51 fn = getattr(context, 'parse_constant', None)52 if fn is None:53 rval = c[s]54 else:55 rval = fn(s)56 return rval, None57 pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant)58 59 60 def JSONNumber(match, context):61 match = JSONNumber.regex.match(match.string, *match.span())62 integer, frac, exp = match.groups()63 if frac or exp:64 fn = getattr(context, 'parse_float', None) or float65 res = fn(integer + (frac or '') + (exp or ''))66 else:67 fn = getattr(context, 'parse_int', None) or int68 res = fn(integer)69 return res, None70 pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber)71 72 56 73 57 STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) … … 79 63 DEFAULT_ENCODING = "utf-8" 80 64 81 82 def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match): 65 def py_scanstring(s, end, encoding=None, strict=True, 66 _b=BACKSLASH, _m=STRINGCHUNK.match): 67 """Scan the string s for a JSON string. End is the index of the 68 character in s after the quote that started the JSON string. 69 Unescapes all valid JSON string escape sequences and raises ValueError 70 on attempt to decode an invalid string. If strict is False then literal 71 control characters are allowed in the string. 72 73 Returns a tuple of the decoded string and the index of the character in s 74 after the end quote.""" 83 75 if encoding is None: 84 76 encoding = DEFAULT_ENCODING … … 93 85 end = chunk.end() 94 86 content, terminator = chunk.groups() 87 # Content is contains zero or more unescaped string characters 95 88 if content: 96 89 if not isinstance(content, unicode): 97 90 content = unicode(content, encoding) 98 91 _append(content) 92 # Terminator is the end of string, a literal control character, 93 # or a backslash denoting that an escape sequence follows 99 94 if terminator == '"': 100 95 break 101 96 elif terminator != '\\': 102 97 if strict: 98 #msg = "Invalid control character %r at" % (terminator,) 103 99 msg = "Invalid control character {0!r} at".format(terminator) 104 100 raise ValueError(errmsg(msg, s, end)) … … 111 107 raise ValueError( 112 108 errmsg("Unterminated string starting at", s, begin)) 109 # If not a unicode escape sequence, must be in the lookup table 113 110 if esc != 'u': 114 111 try: 115 m= _b[esc]112 char = _b[esc] 116 113 except KeyError: 117 msg = "Invalid \\escape: {0!r}".format(esc)114 msg = "Invalid \\escape: " + repr(esc) 118 115 raise ValueError(errmsg(msg, s, end)) 119 116 end += 1 120 117 else: 118 # Unicode escape sequence 121 119 esc = s[end + 1:end + 5] 122 120 next_end = end + 5 123 msg = "Invalid \\uXXXX escape" 124 try: 125 if len(esc) != 4: 126 raise ValueError 127 uni = int(esc, 16) 128 if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: 129 msg = "Invalid \\uXXXX\\uXXXX surrogate pair" 130 if not s[end + 5:end + 7] == '\\u': 131 raise ValueError 132 esc2 = s[end + 7:end + 11] 133 if len(esc2) != 4: 134 raise ValueError 135 uni2 = int(esc2, 16) 136 uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) 137 next_end += 6 138 m = unichr(uni) 139 except ValueError: 121 if len(esc) != 4: 122 msg = "Invalid \\uXXXX escape" 140 123 raise ValueError(errmsg(msg, s, end)) 124 uni = int(esc, 16) 125 # Check for surrogate pair on UCS-4 systems 126 if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: 127 msg = "Invalid \\uXXXX\\uXXXX surrogate pair" 128 if not s[end + 5:end + 7] == '\\u': 129 raise ValueError(errmsg(msg, s, end)) 130 esc2 = s[end + 7:end + 11] 131 if len(esc2) != 4: 132 raise ValueError(errmsg(msg, s, end)) 133 uni2 = int(esc2, 16) 134 uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) 135 next_end += 6 136 char = unichr(uni) 141 137 end = next_end 142 _append(m) 138 # Append the unescaped character 139 _append(char) 143 140 return u''.join(chunks), end 144 141 145 142 146 # Use speedup 147 if c_scanstring is not None: 148 scanstring = c_scanstring 149 else: 150 scanstring = py_scanstring 151 152 def JSONString(match, context): 153 encoding = getattr(context, 'encoding', None) 154 strict = getattr(context, 'strict', True) 155 return scanstring(match.string, match.end(), encoding, strict) 156 pattern(r'"')(JSONString) 157 158 159 WHITESPACE = re.compile(r'\s*', FLAGS) 160 161 162 def JSONObject(match, context, _w=WHITESPACE.match): 163 pairs = {} 164 s = match.string 165 end = _w(s, match.end()).end() 143 # Use speedup if available 144 scanstring = c_scanstring or py_scanstring 145 146 WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) 147 WHITESPACE_STR = ' \t\n\r' 148 149 def JSONObject(s_and_end, encoding, strict, scan_once, object_hook, 150 object_pairs_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR): 151 s, end = s_and_end 152 pairs = [] 153 pairs_append = pairs.append 154 # Use a slice to prevent IndexError from being raised, the following 155 # check will raise a more specific ValueError if the string is empty 166 156 nextchar = s[end:end + 1] 167 # Trivial empty object 168 if nextchar == '}': 169 return pairs, end + 1 157 # Normally we expect nextchar == '"' 170 158 if nextchar != '"': 171 raise ValueError(errmsg("Expecting property name", s, end)) 159 if nextchar in _ws: 160 end = _w(s, end).end() 161 nextchar = s[end:end + 1] 162 # Trivial empty object 163 if nextchar == '}': 164 if object_pairs_hook is not None: 165 result = object_pairs_hook(pairs) 166 return result, end + 1 167 pairs = {} 168 if object_hook is not None: 169 pairs = object_hook(pairs) 170 return pairs, end + 1 171 elif nextchar != '"': 172 raise ValueError(errmsg( 173 "Expecting property name enclosed in double quotes", s, end)) 172 174 end += 1 173 encoding = getattr(context, 'encoding', None)174 strict = getattr(context, 'strict', True)175 iterscan = JSONScanner.iterscan176 175 while True: 177 176 key, end = scanstring(s, end, encoding, strict) 178 end = _w(s, end).end() 177 178 # To skip some function call overhead we optimize the fast paths where 179 # the JSON key separator is ": " or just ":". 179 180 if s[end:end + 1] != ':': 180 raise ValueError(errmsg("Expecting : delimiter", s, end)) 181 end = _w(s, end + 1).end() 182 try: 183 value, end = iterscan(s, idx=end, context=context).next() 181 end = _w(s, end).end() 182 if s[end:end + 1] != ':': 183 raise ValueError(errmsg("Expecting ':' delimiter", s, end)) 184 end += 1 185 186 try: 187 if s[end] in _ws: 188 end += 1 189 if s[end] in _ws: 190 end = _w(s, end + 1).end() 191 except IndexError: 192 pass 193 194 try: 195 value, end = scan_once(s, end) 184 196 except StopIteration: 185 197 raise ValueError(errmsg("Expecting object", s, end)) 186 pairs[key] = value 187 end = _w(s, end).end() 188 nextchar = s[end:end + 1] 198 pairs_append((key, value)) 199 200 try: 201 nextchar = s[end] 202 if nextchar in _ws: 203 end = _w(s, end + 1).end() 204 nextchar = s[end] 205 except IndexError: 206 nextchar = '' 189 207 end += 1 208 190 209 if nextchar == '}': 191 210 break 192 if nextchar != ',': 193 raise ValueError(errmsg("Expecting , delimiter", s, end - 1)) 194 end = _w(s, end).end() 195 nextchar = s[end:end + 1] 211 elif nextchar != ',': 212 raise ValueError(errmsg("Expecting ',' delimiter", s, end - 1)) 213 214 try: 215 nextchar = s[end] 216 if nextchar in _ws: 217 end += 1 218 nextchar = s[end] 219 if nextchar in _ws: 220 end = _w(s, end + 1).end() 221 nextchar = s[end] 222 except IndexError: 223 nextchar = '' 224 196 225 end += 1 197 226 if nextchar != '"': 198 raise ValueError(errmsg("Expecting property name", s, end - 1)) 199 object_hook = getattr(context, 'object_hook', None) 227 raise ValueError(errmsg( 228 "Expecting property name enclosed in double quotes", s, end - 1)) 229 if object_pairs_hook is not None: 230 result = object_pairs_hook(pairs) 231 return result, end 232 pairs = dict(pairs) 200 233 if object_hook is not None: 201 234 pairs = object_hook(pairs) 202 235 return pairs, end 203 pattern(r'{')(JSONObject) 204 205 206 def JSONArray(match, context, _w=WHITESPACE.match): 236 237 def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): 238 s, end = s_and_end 207 239 values = [] 208 s = match.string 209 end = _w(s, match.end()).end() 240 nextchar = s[end:end + 1] 241 if nextchar in _ws: 242 end = _w(s, end + 1).end() 243 nextchar = s[end:end + 1] 210 244 # Look-ahead for trivial empty array 211 nextchar = s[end:end + 1]212 245 if nextchar == ']': 213 246 return values, end + 1 214 iterscan = JSONScanner.iterscan247 _append = values.append 215 248 while True: 216 249 try: 217 value, end = iterscan(s, idx=end, context=context).next()250 value, end = scan_once(s, end) 218 251 except StopIteration: 219 252 raise ValueError(errmsg("Expecting object", s, end)) 220 values.append(value) 221 end = _w(s, end).end() 253 _append(value) 222 254 nextchar = s[end:end + 1] 255 if nextchar in _ws: 256 end = _w(s, end + 1).end() 257 nextchar = s[end:end + 1] 223 258 end += 1 224 259 if nextchar == ']': 225 260 break 226 if nextchar != ',': 227 raise ValueError(errmsg("Expecting , delimiter", s, end)) 228 end = _w(s, end).end() 261 elif nextchar != ',': 262 raise ValueError(errmsg("Expecting ',' delimiter", s, end)) 263 try: 264 if s[end] in _ws: 265 end += 1 266 if s[end] in _ws: 267 end = _w(s, end + 1).end() 268 except IndexError: 269 pass 270 229 271 return values, end 230 pattern(r'\[')(JSONArray)231 232 233 ANYTHING = [234 JSONObject,235 JSONArray,236 JSONString,237 JSONConstant,238 JSONNumber,239 ]240 241 JSONScanner = Scanner(ANYTHING)242 243 272 244 273 class JSONDecoder(object): … … 269 298 It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as 270 299 their corresponding ``float`` values, which is outside the JSON spec. 300 271 301 """ 272 302 273 _scanner = Scanner(ANYTHING)274 __all__ = ['__init__', 'decode', 'raw_decode']275 276 303 def __init__(self, encoding=None, object_hook=None, parse_float=None, 277 parse_int=None, parse_constant=None, strict=True): 304 parse_int=None, parse_constant=None, strict=True, 305 object_pairs_hook=None): 278 306 """``encoding`` determines the encoding used to interpret any ``str`` 279 307 objects decoded by this instance (utf-8 by default). It has no … … 283 311 strings of other encodings should be passed in as ``unicode``. 284 312 285 ``object_hook``, if specified, will be called with the result of286 every JSON object decoded and its return value will be used in313 ``object_hook``, if specified, will be called with the result 314 of every JSON object decoded and its return value will be used in 287 315 place of the given ``dict``. This can be used to provide custom 288 316 deserializations (e.g. to support JSON-RPC class hinting). 317 318 ``object_pairs_hook``, if specified will be called with the result of 319 every JSON object decoded with an ordered list of pairs. The return 320 value of ``object_pairs_hook`` will be used instead of the ``dict``. 321 This feature can be used to implement custom decoders that rely on the 322 order that the key and value pairs are decoded (for example, 323 collections.OrderedDict will remember the order of insertion). If 324 ``object_hook`` is also defined, the ``object_pairs_hook`` takes 325 priority. 289 326 290 327 ``parse_float``, if specified, will be called with the string … … 299 336 300 337 ``parse_constant``, if specified, will be called with one of the 301 following strings: -Infinity, Infinity, NaN , null, true, false.338 following strings: -Infinity, Infinity, NaN. 302 339 This can be used to raise an exception if invalid JSON numbers 303 340 are encountered. 341 342 If ``strict`` is false (true is the default), then control 343 characters will be allowed inside strings. Control characters in 344 this context are those with character codes in the 0-31 range, 345 including ``'\\t'`` (tab), ``'\\n'``, ``'\\r'`` and ``'\\0'``. 304 346 305 347 """ 306 348 self.encoding = encoding 307 349 self.object_hook = object_hook 308 self.parse_float = parse_float 309 self.parse_int = parse_int 310 self.parse_constant = parse_constant 350 self.object_pairs_hook = object_pairs_hook 351 self.parse_float = parse_float or float 352 self.parse_int = parse_int or int 353 self.parse_constant = parse_constant or _CONSTANTS.__getitem__ 311 354 self.strict = strict 355 self.parse_object = JSONObject 356 self.parse_array = JSONArray 357 self.parse_string = scanstring 358 self.scan_once = scanner.make_scanner(self) 312 359 313 360 def decode(self, s, _w=WHITESPACE.match): 314 """ 315 Return the Python representation of ``s`` (a ``str`` or ``unicode`` 361 """Return the Python representation of ``s`` (a ``str`` or ``unicode`` 316 362 instance containing a JSON document) 317 363 … … 323 369 return obj 324 370 325 def raw_decode(self, s, **kw):326 """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning327 with a JSON document) and return a 2-tuple of the Python371 def raw_decode(self, s, idx=0): 372 """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` 373 beginning with a JSON document) and return a 2-tuple of the Python 328 374 representation and the index in ``s`` where the document ended. 329 375 … … 332 378 333 379 """ 334 kw.setdefault('context', self) 335 try: 336 obj, end = self._scanner.iterscan(s, **kw).next() 380 try: 381 obj, end = self.scan_once(s, idx) 337 382 except StopIteration: 338 383 raise ValueError("No JSON object could be decoded") -
python/trunk/Lib/json/encoder.py
r2 r391 1 1 """Implementation of JSONEncoder 2 2 """ 3 4 3 import re 5 import math6 4 7 5 try: … … 9 7 except ImportError: 10 8 c_encode_basestring_ascii = None 11 12 __all__ = ['JSONEncoder'] 9 try: 10 from _json import make_encoder as c_make_encoder 11 except ImportError: 12 c_make_encoder = None 13 13 14 14 ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') … … 26 26 for i in range(0x20): 27 27 ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) 28 28 #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) 29 30 INFINITY = float('inf') 29 31 FLOAT_REPR = repr 30 31 def floatstr(o, allow_nan=True):32 # Check for specials. Note that this type of test is processor- and/or33 # 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 text50 51 32 52 33 def encode_basestring(s): … … 60 41 61 42 def py_encode_basestring_ascii(s): 43 """Return an ASCII-only JSON representation of a Python string 44 45 """ 62 46 if isinstance(s, str) and HAS_UTF8.search(s) is not None: 63 47 s = s.decode('utf-8') … … 70 54 if n < 0x10000: 71 55 return '\\u{0:04x}'.format(n) 56 #return '\\u%04x' % (n,) 72 57 else: 73 58 # surrogate pair … … 76 61 s2 = 0xdc00 | (n & 0x3ff) 77 62 return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) 63 #return '\\u%04x\\u%04x' % (s1, s2) 78 64 return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' 79 65 80 66 81 if c_encode_basestring_ascii is not None: 82 encode_basestring_ascii = c_encode_basestring_ascii 83 else: 84 encode_basestring_ascii = py_encode_basestring_ascii 85 67 encode_basestring_ascii = ( 68 c_encode_basestring_ascii or py_encode_basestring_ascii) 86 69 87 70 class JSONEncoder(object): … … 114 97 115 98 """ 116 __all__ = ['__init__', 'default', 'encode', 'iterencode']117 99 item_separator = ', ' 118 100 key_separator = ': ' … … 122 104 """Constructor for JSONEncoder, with sensible defaults. 123 105 124 If skipkeys is False, then it is a TypeError to attempt106 If skipkeys is false, then it is a TypeError to attempt 125 107 encoding of keys that are not str, int, long, float or None. If 126 108 skipkeys is True, such items are simply skipped. 127 109 128 If ensure_ascii is True, the output is guaranteed to be str 129 objects with all incoming unicode characters escaped. If 130 ensure_ascii is false, the output will be unicode object. 131 132 If check_circular is True, then lists, dicts, and custom encoded 110 If *ensure_ascii* is true (the default), all non-ASCII 111 characters in the output are escaped with \uXXXX sequences, 112 and the results are str instances consisting of ASCII 113 characters only. If ensure_ascii is False, a result may be a 114 unicode instance. This usually happens if the input contains 115 unicode strings or the *encoding* parameter is used. 116 117 If check_circular is true, then lists, dicts, and custom encoded 133 118 objects will be checked for circular references during encoding to 134 119 prevent an infinite recursion (which would cause an OverflowError). 135 120 Otherwise, no such check takes place. 136 121 137 If allow_nan is True, then NaN, Infinity, and -Infinity will be122 If allow_nan is true, then NaN, Infinity, and -Infinity will be 138 123 encoded as such. This behavior is not JSON specification compliant, 139 124 but is consistent with most JavaScript based encoders and decoders. 140 125 Otherwise, it will be a ValueError to encode such floats. 141 126 142 If sort_keys is True, then the output of dictionaries will be127 If sort_keys is true, then the output of dictionaries will be 143 128 sorted by key; this is useful for regression tests to ensure 144 129 that JSON serializations can be compared on a day-to-day basis. … … 147 132 elements and object members will be pretty-printed with that 148 133 indent level. An indent level of 0 will only insert newlines. 149 None is the most compact representation. 134 None is the most compact representation. Since the default 135 item separator is ', ', the output might include trailing 136 whitespace when indent is specified. You can use 137 separators=(',', ': ') to avoid this. 150 138 151 139 If specified, separators should be a (item_separator, key_separator) … … 162 150 163 151 """ 152 164 153 self.skipkeys = skipkeys 165 154 self.ensure_ascii = ensure_ascii … … 168 157 self.sort_keys = sort_keys 169 158 self.indent = indent 170 self.current_indent_level = 0171 159 if separators is not None: 172 160 self.item_separator, self.key_separator = separators … … 175 163 self.encoding = encoding 176 164 177 def _newline_indent(self):178 return '\n' + (' ' * (self.indent * self.current_indent_level))179 180 def _iterencode_list(self, lst, markers=None):181 if not lst:182 yield '[]'183 return184 if markers is not None:185 markerid = id(lst)186 if markerid in markers:187 raise ValueError("Circular reference detected")188 markers[markerid] = lst189 yield '['190 if self.indent is not None:191 self.current_indent_level += 1192 newline_indent = self._newline_indent()193 separator = self.item_separator + newline_indent194 yield newline_indent195 else:196 newline_indent = None197 separator = self.item_separator198 first = True199 for value in lst:200 if first:201 first = False202 else:203 yield separator204 for chunk in self._iterencode(value, markers):205 yield chunk206 if newline_indent is not None:207 self.current_indent_level -= 1208 yield self._newline_indent()209 yield ']'210 if markers is not None:211 del markers[markerid]212 213 def _iterencode_dict(self, dct, markers=None):214 if not dct:215 yield '{}'216 return217 if markers is not None:218 markerid = id(dct)219 if markerid in markers:220 raise ValueError("Circular reference detected")221 markers[markerid] = dct222 yield '{'223 key_separator = self.key_separator224 if self.indent is not None:225 self.current_indent_level += 1226 newline_indent = self._newline_indent()227 item_separator = self.item_separator + newline_indent228 yield newline_indent229 else:230 newline_indent = None231 item_separator = self.item_separator232 first = True233 if self.ensure_ascii:234 encoder = encode_basestring_ascii235 else:236 encoder = encode_basestring237 allow_nan = self.allow_nan238 if self.sort_keys:239 keys = dct.keys()240 keys.sort()241 items = [(k, dct[k]) for k in keys]242 else:243 items = dct.iteritems()244 _encoding = self.encoding245 _do_decode = (_encoding is not None246 and not (_encoding == 'utf-8'))247 for key, value in items:248 if isinstance(key, str):249 if _do_decode:250 key = key.decode(_encoding)251 elif isinstance(key, basestring):252 pass253 # JavaScript is weakly typed for these, so it makes sense to254 # also allow them. Many encoders seem to do something like this.255 elif isinstance(key, float):256 key = floatstr(key, allow_nan)257 elif isinstance(key, (int, long)):258 key = str(key)259 elif key is True:260 key = 'true'261 elif key is False:262 key = 'false'263 elif key is None:264 key = 'null'265 elif self.skipkeys:266 continue267 else:268 raise TypeError("key {0!r} is not a string".format(key))269 if first:270 first = False271 else:272 yield item_separator273 yield encoder(key)274 yield key_separator275 for chunk in self._iterencode(value, markers):276 yield chunk277 if newline_indent is not None:278 self.current_indent_level -= 1279 yield self._newline_indent()280 yield '}'281 if markers is not None:282 del markers[markerid]283 284 def _iterencode(self, o, markers=None):285 if isinstance(o, basestring):286 if self.ensure_ascii:287 encoder = encode_basestring_ascii288 else:289 encoder = encode_basestring290 _encoding = self.encoding291 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:296 yield 'null'297 elif o is True:298 yield 'true'299 elif o is False:300 yield 'false'301 elif isinstance(o, (int, long)):302 yield str(o)303 elif isinstance(o, float):304 yield floatstr(o, self.allow_nan)305 elif isinstance(o, (list, tuple)):306 for chunk in self._iterencode_list(o, markers):307 yield chunk308 elif isinstance(o, dict):309 for chunk in self._iterencode_dict(o, markers):310 yield chunk311 else:312 if markers is not None:313 markerid = id(o)314 if markerid in markers:315 raise ValueError("Circular reference detected")316 markers[markerid] = o317 for chunk in self._iterencode_default(o, markers):318 yield chunk319 if markers is not None:320 del markers[markerid]321 322 def _iterencode_default(self, o, markers=None):323 newobj = self.default(o)324 return self._iterencode(newobj, markers)325 326 165 def default(self, o): 327 """Implement this method in a subclass such that it returns a serializable328 object for ``o``, or calls the base implementation (to raise a329 ``TypeError``).330 331 For example, to support arbitrary iterators, you could implement332 default like this::166 """Implement this method in a subclass such that it returns 167 a serializable object for ``o``, or calls the base implementation 168 (to raise a ``TypeError``). 169 170 For example, to support arbitrary iterators, you could 171 implement default like this:: 333 172 334 173 def default(self, o): … … 339 178 else: 340 179 return list(iterable) 180 # Let the base class default method raise the TypeError 341 181 return JSONEncoder.default(self, o) 342 182 … … 365 205 # exceptions aren't as detailed. The list call should be roughly 366 206 # equivalent to the PySequence_Fast that ''.join() would do. 367 chunks = list(self.iterencode(o)) 207 chunks = self.iterencode(o, _one_shot=True) 208 if not isinstance(chunks, (list, tuple)): 209 chunks = list(chunks) 368 210 return ''.join(chunks) 369 211 370 def iterencode(self, o ):371 """Encode the given object and yield each string representation as372 available.212 def iterencode(self, o, _one_shot=False): 213 """Encode the given object and yield each string 214 representation as available. 373 215 374 216 For example:: … … 382 224 else: 383 225 markers = None 384 return self._iterencode(o, markers) 226 if self.ensure_ascii: 227 _encoder = encode_basestring_ascii 228 else: 229 _encoder = encode_basestring 230 if self.encoding != 'utf-8': 231 def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): 232 if isinstance(o, str): 233 o = o.decode(_encoding) 234 return _orig_encoder(o) 235 236 def floatstr(o, allow_nan=self.allow_nan, 237 _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY): 238 # Check for specials. Note that this type of test is processor 239 # and/or platform-specific, so do tests which don't depend on the 240 # internals. 241 242 if o != o: 243 text = 'NaN' 244 elif o == _inf: 245 text = 'Infinity' 246 elif o == _neginf: 247 text = '-Infinity' 248 else: 249 return _repr(o) 250 251 if not allow_nan: 252 raise ValueError( 253 "Out of range float values are not JSON compliant: " + 254 repr(o)) 255 256 return text 257 258 259 if (_one_shot and c_make_encoder is not None 260 and self.indent is None and not self.sort_keys): 261 _iterencode = c_make_encoder( 262 markers, self.default, _encoder, self.indent, 263 self.key_separator, self.item_separator, self.sort_keys, 264 self.skipkeys, self.allow_nan) 265 else: 266 _iterencode = _make_iterencode( 267 markers, self.default, _encoder, self.indent, floatstr, 268 self.key_separator, self.item_separator, self.sort_keys, 269 self.skipkeys, _one_shot) 270 return _iterencode(o, 0) 271 272 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, 273 _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, 274 ## HACK: hand-optimized bytecode; turn globals into locals 275 ValueError=ValueError, 276 basestring=basestring, 277 dict=dict, 278 float=float, 279 id=id, 280 int=int, 281 isinstance=isinstance, 282 list=list, 283 long=long, 284 str=str, 285 tuple=tuple, 286 ): 287 288 def _iterencode_list(lst, _current_indent_level): 289 if not lst: 290 yield '[]' 291 return 292 if markers is not None: 293 markerid = id(lst) 294 if markerid in markers: 295 raise ValueError("Circular reference detected") 296 markers[markerid] = lst 297 buf = '[' 298 if _indent is not None: 299 _current_indent_level += 1 300 newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) 301 separator = _item_separator + newline_indent 302 buf += newline_indent 303 else: 304 newline_indent = None 305 separator = _item_separator 306 first = True 307 for value in lst: 308 if first: 309 first = False 310 else: 311 buf = separator 312 if isinstance(value, basestring): 313 yield buf + _encoder(value) 314 elif value is None: 315 yield buf + 'null' 316 elif value is True: 317 yield buf + 'true' 318 elif value is False: 319 yield buf + 'false' 320 elif isinstance(value, (int, long)): 321 yield buf + str(value) 322 elif isinstance(value, float): 323 yield buf + _floatstr(value) 324 else: 325 yield buf 326 if isinstance(value, (list, tuple)): 327 chunks = _iterencode_list(value, _current_indent_level) 328 elif isinstance(value, dict): 329 chunks = _iterencode_dict(value, _current_indent_level) 330 else: 331 chunks = _iterencode(value, _current_indent_level) 332 for chunk in chunks: 333 yield chunk 334 if newline_indent is not None: 335 _current_indent_level -= 1 336 yield '\n' + (' ' * (_indent * _current_indent_level)) 337 yield ']' 338 if markers is not None: 339 del markers[markerid] 340 341 def _iterencode_dict(dct, _current_indent_level): 342 if not dct: 343 yield '{}' 344 return 345 if markers is not None: 346 markerid = id(dct) 347 if markerid in markers: 348 raise ValueError("Circular reference detected") 349 markers[markerid] = dct 350 yield '{' 351 if _indent is not None: 352 _current_indent_level += 1 353 newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) 354 item_separator = _item_separator + newline_indent 355 yield newline_indent 356 else: 357 newline_indent = None 358 item_separator = _item_separator 359 first = True 360 if _sort_keys: 361 items = sorted(dct.items(), key=lambda kv: kv[0]) 362 else: 363 items = dct.iteritems() 364 for key, value in items: 365 if isinstance(key, basestring): 366 pass 367 # JavaScript is weakly typed for these, so it makes sense to 368 # also allow them. Many encoders seem to do something like this. 369 elif isinstance(key, float): 370 key = _floatstr(key) 371 elif key is True: 372 key = 'true' 373 elif key is False: 374 key = 'false' 375 elif key is None: 376 key = 'null' 377 elif isinstance(key, (int, long)): 378 key = str(key) 379 elif _skipkeys: 380 continue 381 else: 382 raise TypeError("key " + repr(key) + " is not a string") 383 if first: 384 first = False 385 else: 386 yield item_separator 387 yield _encoder(key) 388 yield _key_separator 389 if isinstance(value, basestring): 390 yield _encoder(value) 391 elif value is None: 392 yield 'null' 393 elif value is True: 394 yield 'true' 395 elif value is False: 396 yield 'false' 397 elif isinstance(value, (int, long)): 398 yield str(value) 399 elif isinstance(value, float): 400 yield _floatstr(value) 401 else: 402 if isinstance(value, (list, tuple)): 403 chunks = _iterencode_list(value, _current_indent_level) 404 elif isinstance(value, dict): 405 chunks = _iterencode_dict(value, _current_indent_level) 406 else: 407 chunks = _iterencode(value, _current_indent_level) 408 for chunk in chunks: 409 yield chunk 410 if newline_indent is not None: 411 _current_indent_level -= 1 412 yield '\n' + (' ' * (_indent * _current_indent_level)) 413 yield '}' 414 if markers is not None: 415 del markers[markerid] 416 417 def _iterencode(o, _current_indent_level): 418 if isinstance(o, basestring): 419 yield _encoder(o) 420 elif o is None: 421 yield 'null' 422 elif o is True: 423 yield 'true' 424 elif o is False: 425 yield 'false' 426 elif isinstance(o, (int, long)): 427 yield str(o) 428 elif isinstance(o, float): 429 yield _floatstr(o) 430 elif isinstance(o, (list, tuple)): 431 for chunk in _iterencode_list(o, _current_indent_level): 432 yield chunk 433 elif isinstance(o, dict): 434 for chunk in _iterencode_dict(o, _current_indent_level): 435 yield chunk 436 else: 437 if markers is not None: 438 markerid = id(o) 439 if markerid in markers: 440 raise ValueError("Circular reference detected") 441 markers[markerid] = o 442 o = _default(o) 443 for chunk in _iterencode(o, _current_indent_level): 444 yield chunk 445 if markers is not None: 446 del markers[markerid] 447 448 return _iterencode -
python/trunk/Lib/json/scanner.py
r2 r391 1 """Iterator based sre token scanner 1 """JSON token scanner 2 """ 3 import re 4 try: 5 from _json import make_scanner as c_make_scanner 6 except ImportError: 7 c_make_scanner = None 2 8 3 """ 9 __all__ = ['make_scanner'] 4 10 5 import re 6 import sre_parse 7 import sre_compile 8 import sre_constants 11 NUMBER_RE = re.compile( 12 r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?', 13 (re.VERBOSE | re.MULTILINE | re.DOTALL)) 9 14 10 from re import VERBOSE, MULTILINE, DOTALL 11 from sre_constants import BRANCH, SUBPATTERN 15 def py_make_scanner(context): 16 parse_object = context.parse_object 17 parse_array = context.parse_array 18 parse_string = context.parse_string 19 match_number = NUMBER_RE.match 20 encoding = context.encoding 21 strict = context.strict 22 parse_float = context.parse_float 23 parse_int = context.parse_int 24 parse_constant = context.parse_constant 25 object_hook = context.object_hook 26 object_pairs_hook = context.object_pairs_hook 12 27 13 __all__ = ['Scanner', 'pattern'] 28 def _scan_once(string, idx): 29 try: 30 nextchar = string[idx] 31 except IndexError: 32 raise StopIteration 14 33 15 FLAGS = (VERBOSE | MULTILINE | DOTALL) 34 if nextchar == '"': 35 return parse_string(string, idx + 1, encoding, strict) 36 elif nextchar == '{': 37 return parse_object((string, idx + 1), encoding, strict, 38 _scan_once, object_hook, object_pairs_hook) 39 elif nextchar == '[': 40 return parse_array((string, idx + 1), _scan_once) 41 elif nextchar == 'n' and string[idx:idx + 4] == 'null': 42 return None, idx + 4 43 elif nextchar == 't' and string[idx:idx + 4] == 'true': 44 return True, idx + 4 45 elif nextchar == 'f' and string[idx:idx + 5] == 'false': 46 return False, idx + 5 16 47 17 class Scanner(object): 18 def __init__(self, lexicon, flags=FLAGS):19 self.actions = [None]20 # Combine phrases into a compound pattern21 s = sre_parse.Pattern()22 s.flags = flags23 p = []24 for idx, token in enumerate(lexicon):25 phrase = token.pattern26 try:27 subpattern = sre_parse.SubPattern(s,28 [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))])29 except sre_constants.error:30 raise31 p.append(subpattern)32 self.actions.append(token)48 m = match_number(string, idx) 49 if m is not None: 50 integer, frac, exp = m.groups() 51 if frac or exp: 52 res = parse_float(integer + (frac or '') + (exp or '')) 53 else: 54 res = parse_int(integer) 55 return res, m.end() 56 elif nextchar == 'N' and string[idx:idx + 3] == 'NaN': 57 return parse_constant('NaN'), idx + 3 58 elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity': 59 return parse_constant('Infinity'), idx + 8 60 elif nextchar == '-' and string[idx:idx + 9] == '-Infinity': 61 return parse_constant('-Infinity'), idx + 9 62 else: 63 raise StopIteration 33 64 34 s.groups = len(p) + 1 # NOTE(guido): Added to make SRE validation work 35 p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) 36 self.scanner = sre_compile.compile(p) 65 return _scan_once 37 66 38 def iterscan(self, string, idx=0, context=None): 39 """Yield match, end_idx for each match 40 41 """ 42 match = self.scanner.scanner(string, idx).match 43 actions = self.actions 44 lastend = idx 45 end = len(string) 46 while True: 47 m = match() 48 if m is None: 49 break 50 matchbegin, matchend = m.span() 51 if lastend == matchend: 52 break 53 action = actions[m.lastindex] 54 if action is not None: 55 rval, next_pos = action(m, context) 56 if next_pos is not None and next_pos != matchend: 57 # "fast forward" the scanner 58 matchend = next_pos 59 match = self.scanner.scanner(string, matchend).match 60 yield rval, matchend 61 lastend = matchend 62 63 64 def pattern(pattern, flags=FLAGS): 65 def decorator(fn): 66 fn.pattern = pattern 67 fn.regex = re.compile(pattern, flags) 68 return fn 69 return decorator 67 make_scanner = c_make_scanner or py_make_scanner -
python/trunk/Lib/json/tests/__init__.py
r2 r391 1 1 import os 2 2 import sys 3 import json 4 import doctest 3 5 import unittest 4 import doctest 6 7 from test import test_support 8 9 # import json with and without accelerations 10 cjson = test_support.import_fresh_module('json', fresh=['_json']) 11 pyjson = test_support.import_fresh_module('json', blocked=['_json']) 12 13 # create two base classes that will be used by the other tests 14 class PyTest(unittest.TestCase): 15 json = pyjson 16 loads = staticmethod(pyjson.loads) 17 dumps = staticmethod(pyjson.dumps) 18 19 @unittest.skipUnless(cjson, 'requires _json') 20 class CTest(unittest.TestCase): 21 if cjson is not None: 22 json = cjson 23 loads = staticmethod(cjson.loads) 24 dumps = staticmethod(cjson.dumps) 25 26 # test PyTest and CTest checking if the functions come from the right module 27 class TestPyTest(PyTest): 28 def test_pyjson(self): 29 self.assertEqual(self.json.scanner.make_scanner.__module__, 30 'json.scanner') 31 self.assertEqual(self.json.decoder.scanstring.__module__, 32 'json.decoder') 33 self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, 34 'json.encoder') 35 36 class TestCTest(CTest): 37 def test_cjson(self): 38 self.assertEqual(self.json.scanner.make_scanner.__module__, '_json') 39 self.assertEqual(self.json.decoder.scanstring.__module__, '_json') 40 self.assertEqual(self.json.encoder.c_make_encoder.__module__, '_json') 41 self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, 42 '_json') 43 5 44 6 45 here = os.path.dirname(__file__) … … 18 57 19 58 def additional_tests(): 20 import json21 import json.encoder22 import json.decoder23 59 suite = unittest.TestSuite() 24 60 for mod in (json, json.encoder, json.decoder): 25 61 suite.addTest(doctest.DocTestSuite(mod)) 62 suite.addTest(TestPyTest('test_pyjson')) 63 suite.addTest(TestCTest('test_cjson')) 26 64 return suite 27 65 -
python/trunk/Lib/json/tests/test_decode.py
r2 r391 1 1 import decimal 2 from unittest import TestCase 2 from StringIO import StringIO 3 from collections import OrderedDict 4 from json.tests import PyTest, CTest 3 5 4 import json5 6 6 class TestDecode( TestCase):7 class TestDecode(object): 7 8 def test_decimal(self): 8 rval = json.loads('1.1', parse_float=decimal.Decimal)9 self.assert _(isinstance(rval, decimal.Decimal))10 self.assertEqual s(rval, decimal.Decimal('1.1'))9 rval = self.loads('1.1', parse_float=decimal.Decimal) 10 self.assertTrue(isinstance(rval, decimal.Decimal)) 11 self.assertEqual(rval, decimal.Decimal('1.1')) 11 12 12 13 def test_float(self): 13 rval = json.loads('1', parse_int=float) 14 self.assert_(isinstance(rval, float)) 15 self.assertEquals(rval, 1.0) 14 rval = self.loads('1', parse_int=float) 15 self.assertTrue(isinstance(rval, float)) 16 self.assertEqual(rval, 1.0) 17 18 def test_decoder_optimizations(self): 19 # Several optimizations were made that skip over calls to 20 # the whitespace regex, so this test is designed to try and 21 # exercise the uncommon cases. The array cases are already covered. 22 rval = self.loads('{ "key" : "value" , "k":"v" }') 23 self.assertEqual(rval, {"key":"value", "k":"v"}) 24 25 def test_empty_objects(self): 26 self.assertEqual(self.loads('{}'), {}) 27 self.assertEqual(self.loads('[]'), []) 28 self.assertEqual(self.loads('""'), u"") 29 self.assertIsInstance(self.loads('""'), unicode) 30 31 def test_object_pairs_hook(self): 32 s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' 33 p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), 34 ("qrt", 5), ("pad", 6), ("hoy", 7)] 35 self.assertEqual(self.loads(s), eval(s)) 36 self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) 37 self.assertEqual(self.json.load(StringIO(s), 38 object_pairs_hook=lambda x: x), p) 39 od = self.loads(s, object_pairs_hook=OrderedDict) 40 self.assertEqual(od, OrderedDict(p)) 41 self.assertEqual(type(od), OrderedDict) 42 # the object_pairs_hook takes priority over the object_hook 43 self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, 44 object_hook=lambda x: None), 45 OrderedDict(p)) 46 # check that empty objects literals work (see #17368) 47 self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict), 48 OrderedDict()) 49 self.assertEqual(self.loads('{"empty": {}}', 50 object_pairs_hook=OrderedDict), 51 OrderedDict([('empty', OrderedDict())])) 52 53 def test_extra_data(self): 54 s = '[1, 2, 3]5' 55 msg = 'Extra data' 56 self.assertRaisesRegexp(ValueError, msg, self.loads, s) 57 58 def test_invalid_escape(self): 59 s = '["abc\\y"]' 60 msg = 'escape' 61 self.assertRaisesRegexp(ValueError, msg, self.loads, s) 62 63 class TestPyDecode(TestDecode, PyTest): pass 64 class TestCDecode(TestDecode, CTest): pass -
python/trunk/Lib/json/tests/test_default.py
r2 r391 1 from unittest import TestCase1 from json.tests import PyTest, CTest 2 2 3 import json4 3 5 class TestDefault( TestCase):4 class TestDefault(object): 6 5 def test_default(self): 7 self.assertEquals( 8 json.dumps(type, default=repr), 9 json.dumps(repr(type))) 6 self.assertEqual( 7 self.dumps(type, default=repr), 8 self.dumps(repr(type))) 9 10 11 class TestPyDefault(TestDefault, PyTest): pass 12 class TestCDefault(TestDefault, CTest): pass -
python/trunk/Lib/json/tests/test_dump.py
r2 r391 1 from unittest import TestCase2 1 from cStringIO import StringIO 2 from json.tests import PyTest, CTest 3 3 4 import json5 4 6 class TestDump( TestCase):5 class TestDump(object): 7 6 def test_dump(self): 8 7 sio = StringIO() 9 json.dump({}, sio)10 self.assertEqual s(sio.getvalue(), '{}')8 self.json.dump({}, sio) 9 self.assertEqual(sio.getvalue(), '{}') 11 10 12 11 def test_dumps(self): 13 self.assertEquals(json.dumps({}), '{}') 12 self.assertEqual(self.dumps({}), '{}') 13 14 def test_encode_truefalse(self): 15 self.assertEqual(self.dumps( 16 {True: False, False: True}, sort_keys=True), 17 '{"false": true, "true": false}') 18 self.assertEqual(self.dumps( 19 {2: 3.0, 4.0: 5L, False: 1, 6L: True}, sort_keys=True), 20 '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') 21 22 # Issue 16228: Crash on encoding resized list 23 def test_encode_mutated(self): 24 a = [object()] * 10 25 def crasher(obj): 26 del a[-1] 27 self.assertEqual(self.dumps(a, default=crasher), 28 '[null, null, null, null, null]') 29 30 31 class TestPyDump(TestDump, PyTest): pass 32 class TestCDump(TestDump, CTest): pass -
python/trunk/Lib/json/tests/test_encode_basestring_ascii.py
r2 r391 1 from unittest import TestCase 1 from collections import OrderedDict 2 from json.tests import PyTest, CTest 2 3 3 import json.encoder4 4 5 5 CASES = [ … … 22 22 ] 23 23 24 class TestEncodeBaseStringAscii(TestCase): 25 def test_py_encode_basestring_ascii(self): 26 self._test_encode_basestring_ascii(json.encoder.py_encode_basestring_ascii) 24 class TestEncodeBasestringAscii(object): 25 def test_encode_basestring_ascii(self): 26 fname = self.json.encoder.encode_basestring_ascii.__name__ 27 for input_string, expect in CASES: 28 result = self.json.encoder.encode_basestring_ascii(input_string) 29 self.assertEqual(result, expect, 30 '{0!r} != {1!r} for {2}({3!r})'.format( 31 result, expect, fname, input_string)) 27 32 28 def test_c_encode_basestring_ascii(self): 29 self._test_encode_basestring_ascii(json.encoder.c_encode_basestring_ascii) 33 def test_ordered_dict(self): 34 # See issue 6105 35 items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] 36 s = self.dumps(OrderedDict(items)) 37 self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') 30 38 31 def _test_encode_basestring_ascii(self, encode_basestring_ascii): 32 fname = encode_basestring_ascii.__name__ 33 for input_string, expect in CASES: 34 result = encode_basestring_ascii(input_string) 35 self.assertEquals(result, expect) 39 40 class TestPyEncodeBasestringAscii(TestEncodeBasestringAscii, PyTest): pass 41 class TestCEncodeBasestringAscii(TestEncodeBasestringAscii, CTest): pass -
python/trunk/Lib/json/tests/test_fail.py
r2 r391 1 from unittest import TestCase1 from json.tests import PyTest, CTest 2 2 3 import json 4 5 # Fri Dec 30 18:57:26 2005 3 # 2007-10-05 6 4 JSONDOCS = [ 7 5 # http://json.org/JSON_checker/test/fail1.json … … 10 8 '["Unclosed array"', 11 9 # http://json.org/JSON_checker/test/fail3.json 12 '{unquoted_key: "keys must be quoted }',10 '{unquoted_key: "keys must be quoted"}', 13 11 # http://json.org/JSON_checker/test/fail4.json 14 12 '["extra comma",]', … … 36 34 '["Illegal backslash escape: \\x15"]', 37 35 # http://json.org/JSON_checker/test/fail16.json 38 '[ "Illegal backslash escape: \\\'"]',36 '[\\naked]', 39 37 # http://json.org/JSON_checker/test/fail17.json 40 38 '["Illegal backslash escape: \\017"]', … … 53 51 # http://json.org/JSON_checker/test/fail24.json 54 52 "['single quote']", 53 # http://json.org/JSON_checker/test/fail25.json 54 '["\ttab\tcharacter\tin\tstring\t"]', 55 # http://json.org/JSON_checker/test/fail26.json 56 '["tab\\ character\\ in\\ string\\ "]', 57 # http://json.org/JSON_checker/test/fail27.json 58 '["line\nbreak"]', 59 # http://json.org/JSON_checker/test/fail28.json 60 '["line\\\nbreak"]', 61 # http://json.org/JSON_checker/test/fail29.json 62 '[0e]', 63 # http://json.org/JSON_checker/test/fail30.json 64 '[0e+]', 65 # http://json.org/JSON_checker/test/fail31.json 66 '[0e+-1]', 67 # http://json.org/JSON_checker/test/fail32.json 68 '{"Comma instead if closing brace": true,', 69 # http://json.org/JSON_checker/test/fail33.json 70 '["mismatch"}', 55 71 # http://code.google.com/p/simplejson/issues/detail?id=3 56 72 u'["A\u001FZ control characters in string"]', … … 62 78 } 63 79 64 class TestFail( TestCase):80 class TestFail(object): 65 81 def test_failures(self): 66 82 for idx, doc in enumerate(JSONDOCS): 67 83 idx = idx + 1 68 84 if idx in SKIPS: 69 json.loads(doc)85 self.loads(doc) 70 86 continue 71 87 try: 72 json.loads(doc)88 self.loads(doc) 73 89 except ValueError: 74 90 pass 75 91 else: 76 self.fail("Expected failure for fail%d.json: %r" % (idx, doc)) 92 self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc)) 93 94 def test_non_string_keys_dict(self): 95 data = {'a' : 1, (1, 2) : 2} 96 97 #This is for c encoder 98 self.assertRaises(TypeError, self.dumps, data) 99 100 #This is for python encoder 101 self.assertRaises(TypeError, self.dumps, data, indent=True) 102 103 104 class TestPyFail(TestFail, PyTest): pass 105 class TestCFail(TestFail, CTest): pass -
python/trunk/Lib/json/tests/test_float.py
r2 r391 1 1 import math 2 from unittest import TestCase2 from json.tests import PyTest, CTest 3 3 4 import json5 4 6 class TestFloat( TestCase):5 class TestFloat(object): 7 6 def test_floats(self): 8 for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100]: 9 self.assertEquals(float(json.dumps(num)), num) 7 for num in [1617161771.7650001, math.pi, math.pi**100, 8 math.pi**-100, 3.1]: 9 self.assertEqual(float(self.dumps(num)), num) 10 self.assertEqual(self.loads(self.dumps(num)), num) 11 self.assertEqual(self.loads(unicode(self.dumps(num))), num) 12 13 def test_ints(self): 14 for num in [1, 1L, 1<<32, 1<<64]: 15 self.assertEqual(self.dumps(num), str(num)) 16 self.assertEqual(int(self.dumps(num)), num) 17 self.assertEqual(self.loads(self.dumps(num)), num) 18 self.assertEqual(self.loads(unicode(self.dumps(num))), num) 19 20 def test_out_of_range(self): 21 self.assertEqual(self.loads('[23456789012E666]'), [float('inf')]) 22 self.assertEqual(self.loads('[-23456789012E666]'), [float('-inf')]) 23 24 def test_allow_nan(self): 25 for val in (float('inf'), float('-inf'), float('nan')): 26 out = self.dumps([val]) 27 if val == val: # inf 28 self.assertEqual(self.loads(out), [val]) 29 else: # nan 30 res = self.loads(out) 31 self.assertEqual(len(res), 1) 32 self.assertNotEqual(res[0], res[0]) 33 self.assertRaises(ValueError, self.dumps, [val], allow_nan=False) 34 35 36 class TestPyFloat(TestFloat, PyTest): pass 37 class TestCFloat(TestFloat, CTest): pass -
python/trunk/Lib/json/tests/test_indent.py
r2 r391 1 from unittest import TestCase 1 import textwrap 2 from StringIO import StringIO 3 from json.tests import PyTest, CTest 2 4 3 import json4 import textwrap5 5 6 class TestIndent( TestCase):6 class TestIndent(object): 7 7 def test_indent(self): 8 8 h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', … … 31 31 32 32 33 d1 = json.dumps(h)34 d2 = json.dumps(h, indent=2, sort_keys=True, separators=(',', ': '))33 d1 = self.dumps(h) 34 d2 = self.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) 35 35 36 h1 = json.loads(d1)37 h2 = json.loads(d2)36 h1 = self.loads(d1) 37 h2 = self.loads(d2) 38 38 39 self.assertEquals(h1, h) 40 self.assertEquals(h2, h) 41 self.assertEquals(d2, expect) 39 self.assertEqual(h1, h) 40 self.assertEqual(h2, h) 41 self.assertEqual(d2, expect) 42 43 def test_indent0(self): 44 h = {3: 1} 45 def check(indent, expected): 46 d1 = self.dumps(h, indent=indent) 47 self.assertEqual(d1, expected) 48 49 sio = StringIO() 50 self.json.dump(h, sio, indent=indent) 51 self.assertEqual(sio.getvalue(), expected) 52 53 # indent=0 should emit newlines 54 check(0, '{\n"3": 1\n}') 55 # indent=None is more compact 56 check(None, '{"3": 1}') 57 58 59 class TestPyIndent(TestIndent, PyTest): pass 60 class TestCIndent(TestIndent, CTest): pass -
python/trunk/Lib/json/tests/test_pass1.py
r2 r391 1 from unittest import TestCase1 from json.tests import PyTest, CTest 2 2 3 import json4 3 5 4 # from http://json.org/JSON_checker/test/pass1.json … … 19 18 "e": 0.123456789e-12, 20 19 "E": 1.234567890E+34, 21 "": 23456789012E66 6,20 "": 23456789012E66, 22 21 "zero": 0, 23 22 "one": 1, … … 30 29 "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", 31 30 "digit": "0123456789", 31 "0123456789": "digit", 32 32 "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?", 33 33 "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", … … 45 45 , 46 46 47 4 , 5 , 6 ,7 ], 48 "compact": [1,2,3,4,5,6,7], 47 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], 49 48 "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", 50 49 "quotes": "" \u0022 %22 0x22 034 "", … … 57 56 , 58 57 59 1066 60 61 58 1066, 59 1e1, 60 0.1e1, 61 1e-1, 62 1e00,2e+00,2e-00 62 63 ,"rosebud"] 63 64 ''' 64 65 65 class TestPass1( TestCase):66 class TestPass1(object): 66 67 def test_parse(self): 67 68 # test in/out equivalence and parsing 68 res = json.loads(JSON) 69 out = json.dumps(res) 70 self.assertEquals(res, json.loads(out)) 71 try: 72 json.dumps(res, allow_nan=False) 73 except ValueError: 74 pass 75 else: 76 self.fail("23456789012E666 should be out of range") 69 res = self.loads(JSON) 70 out = self.dumps(res) 71 self.assertEqual(res, self.loads(out)) 72 73 74 class TestPyPass1(TestPass1, PyTest): pass 75 class TestCPass1(TestPass1, CTest): pass -
python/trunk/Lib/json/tests/test_pass2.py
r2 r391 1 from unittest import TestCase2 import json 1 from json.tests import PyTest, CTest 2 3 3 4 4 # from http://json.org/JSON_checker/test/pass2.json … … 7 7 ''' 8 8 9 class TestPass2( TestCase):9 class TestPass2(object): 10 10 def test_parse(self): 11 11 # test in/out equivalence and parsing 12 res = json.loads(JSON) 13 out = json.dumps(res) 14 self.assertEquals(res, json.loads(out)) 12 res = self.loads(JSON) 13 out = self.dumps(res) 14 self.assertEqual(res, self.loads(out)) 15 16 17 class TestPyPass2(TestPass2, PyTest): pass 18 class TestCPass2(TestPass2, CTest): pass -
python/trunk/Lib/json/tests/test_pass3.py
r2 r391 1 from unittest import TestCase1 from json.tests import PyTest, CTest 2 2 3 import json4 3 5 4 # from http://json.org/JSON_checker/test/pass3.json … … 13 12 ''' 14 13 15 class TestPass3(TestCase): 14 15 class TestPass3(object): 16 16 def test_parse(self): 17 17 # test in/out equivalence and parsing 18 res = json.loads(JSON) 19 out = json.dumps(res) 20 self.assertEquals(res, json.loads(out)) 18 res = self.loads(JSON) 19 out = self.dumps(res) 20 self.assertEqual(res, self.loads(out)) 21 22 23 class TestPyPass3(TestPass3, PyTest): pass 24 class TestCPass3(TestPass3, CTest): pass -
python/trunk/Lib/json/tests/test_recursion.py
r2 r391 1 from unittest import TestCase1 from json.tests import PyTest, CTest 2 2 3 import json4 3 5 4 class JSONTestObject: … … 7 6 8 7 9 class RecursiveJSONEncoder(json.JSONEncoder): 10 recurse = False 11 def default(self, o): 12 if o is JSONTestObject: 13 if self.recurse: 14 return [JSONTestObject] 15 else: 16 return 'JSONTestObject' 17 return json.JSONEncoder.default(o) 18 19 20 class TestRecursion(TestCase): 8 class TestRecursion(object): 21 9 def test_listrecursion(self): 22 10 x = [] 23 11 x.append(x) 24 12 try: 25 json.dumps(x)13 self.dumps(x) 26 14 except ValueError: 27 15 pass … … 32 20 x.append(y) 33 21 try: 34 json.dumps(x)22 self.dumps(x) 35 23 except ValueError: 36 24 pass … … 40 28 x = [y, y] 41 29 # ensure that the marker is cleared 42 json.dumps(x)30 self.dumps(x) 43 31 44 32 def test_dictrecursion(self): … … 46 34 x["test"] = x 47 35 try: 48 json.dumps(x)36 self.dumps(x) 49 37 except ValueError: 50 38 pass … … 54 42 y = {"a": x, "b": x} 55 43 # ensure that the marker is cleared 56 json.dumps(x)44 self.dumps(x) 57 45 58 46 def test_defaultrecursion(self): 47 class RecursiveJSONEncoder(self.json.JSONEncoder): 48 recurse = False 49 def default(self, o): 50 if o is JSONTestObject: 51 if self.recurse: 52 return [JSONTestObject] 53 else: 54 return 'JSONTestObject' 55 return pyjson.JSONEncoder.default(o) 56 59 57 enc = RecursiveJSONEncoder() 60 self.assertEqual s(enc.encode(JSONTestObject), '"JSONTestObject"')58 self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"') 61 59 enc.recurse = True 62 60 try: … … 66 64 else: 67 65 self.fail("didn't raise ValueError on default recursion") 66 67 68 def test_highly_nested_objects_decoding(self): 69 # test that loading highly-nested objects doesn't segfault when C 70 # accelerations are used. See #12017 71 # str 72 with self.assertRaises(RuntimeError): 73 self.loads('{"a":' * 100000 + '1' + '}' * 100000) 74 with self.assertRaises(RuntimeError): 75 self.loads('{"a":' * 100000 + '[1]' + '}' * 100000) 76 with self.assertRaises(RuntimeError): 77 self.loads('[' * 100000 + '1' + ']' * 100000) 78 # unicode 79 with self.assertRaises(RuntimeError): 80 self.loads(u'{"a":' * 100000 + u'1' + u'}' * 100000) 81 with self.assertRaises(RuntimeError): 82 self.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000) 83 with self.assertRaises(RuntimeError): 84 self.loads(u'[' * 100000 + u'1' + u']' * 100000) 85 86 def test_highly_nested_objects_encoding(self): 87 # See #12051 88 l, d = [], {} 89 for x in xrange(100000): 90 l, d = [l], {'k':d} 91 with self.assertRaises(RuntimeError): 92 self.dumps(l) 93 with self.assertRaises(RuntimeError): 94 self.dumps(d) 95 96 def test_endless_recursion(self): 97 # See #12051 98 class EndlessJSONEncoder(self.json.JSONEncoder): 99 def default(self, o): 100 """If check_circular is False, this will keep adding another list.""" 101 return [o] 102 103 with self.assertRaises(RuntimeError): 104 EndlessJSONEncoder(check_circular=False).encode(5j) 105 106 107 class TestPyRecursion(TestRecursion, PyTest): pass 108 class TestCRecursion(TestRecursion, CTest): pass -
python/trunk/Lib/json/tests/test_scanstring.py
r2 r391 1 1 import sys 2 import decimal 3 from unittest import TestCase 2 from json.tests import PyTest, CTest 4 3 5 import json6 import json.decoder7 4 8 class TestScanString(TestCase): 9 def test_py_scanstring(self): 10 self._test_scanstring(json.decoder.py_scanstring) 11 12 def test_c_scanstring(self): 13 self._test_scanstring(json.decoder.c_scanstring) 14 15 def _test_scanstring(self, scanstring): 16 self.assertEquals( 5 class TestScanstring(object): 6 def test_scanstring(self): 7 scanstring = self.json.decoder.scanstring 8 self.assertEqual( 17 9 scanstring('"z\\ud834\\udd20x"', 1, None, True), 18 10 (u'z\U0001d120x', 16)) 19 11 20 12 if sys.maxunicode == 65535: 21 self.assertEqual s(13 self.assertEqual( 22 14 scanstring(u'"z\U0001d120x"', 1, None, True), 23 15 (u'z\U0001d120x', 6)) 24 16 else: 25 self.assertEqual s(17 self.assertEqual( 26 18 scanstring(u'"z\U0001d120x"', 1, None, True), 27 19 (u'z\U0001d120x', 5)) 28 20 29 self.assertEqual s(21 self.assertEqual( 30 22 scanstring('"\\u007b"', 1, None, True), 31 23 (u'{', 8)) 32 24 33 self.assertEqual s(25 self.assertEqual( 34 26 scanstring('"A JSON payload should be an object or array, not a string."', 1, None, True), 35 27 (u'A JSON payload should be an object or array, not a string.', 60)) 36 28 37 self.assertEqual s(29 self.assertEqual( 38 30 scanstring('["Unclosed array"', 2, None, True), 39 31 (u'Unclosed array', 17)) 40 32 41 self.assertEqual s(33 self.assertEqual( 42 34 scanstring('["extra comma",]', 2, None, True), 43 35 (u'extra comma', 14)) 44 36 45 self.assertEqual s(37 self.assertEqual( 46 38 scanstring('["double extra comma",,]', 2, None, True), 47 39 (u'double extra comma', 21)) 48 40 49 self.assertEqual s(41 self.assertEqual( 50 42 scanstring('["Comma after the close"],', 2, None, True), 51 43 (u'Comma after the close', 24)) 52 44 53 self.assertEqual s(45 self.assertEqual( 54 46 scanstring('["Extra close"]]', 2, None, True), 55 47 (u'Extra close', 14)) 56 48 57 self.assertEqual s(49 self.assertEqual( 58 50 scanstring('{"Extra comma": true,}', 2, None, True), 59 51 (u'Extra comma', 14)) 60 52 61 self.assertEqual s(53 self.assertEqual( 62 54 scanstring('{"Extra value after close": true} "misplaced quoted value"', 2, None, True), 63 55 (u'Extra value after close', 26)) 64 56 65 self.assertEqual s(57 self.assertEqual( 66 58 scanstring('{"Illegal expression": 1 + 2}', 2, None, True), 67 59 (u'Illegal expression', 21)) 68 60 69 self.assertEqual s(61 self.assertEqual( 70 62 scanstring('{"Illegal invocation": alert()}', 2, None, True), 71 63 (u'Illegal invocation', 21)) 72 64 73 self.assertEqual s(65 self.assertEqual( 74 66 scanstring('{"Numbers cannot have leading zeroes": 013}', 2, None, True), 75 67 (u'Numbers cannot have leading zeroes', 37)) 76 68 77 self.assertEqual s(69 self.assertEqual( 78 70 scanstring('{"Numbers cannot be hex": 0x14}', 2, None, True), 79 71 (u'Numbers cannot be hex', 24)) 80 72 81 self.assertEqual s(73 self.assertEqual( 82 74 scanstring('[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', 21, None, True), 83 75 (u'Too deep', 30)) 84 76 85 self.assertEqual s(77 self.assertEqual( 86 78 scanstring('{"Missing colon" null}', 2, None, True), 87 79 (u'Missing colon', 16)) 88 80 89 self.assertEqual s(81 self.assertEqual( 90 82 scanstring('{"Double colon":: null}', 2, None, True), 91 83 (u'Double colon', 15)) 92 84 93 self.assertEqual s(85 self.assertEqual( 94 86 scanstring('{"Comma instead of colon", null}', 2, None, True), 95 87 (u'Comma instead of colon', 25)) 96 88 97 self.assertEqual s(89 self.assertEqual( 98 90 scanstring('["Colon instead of comma": false]', 2, None, True), 99 91 (u'Colon instead of comma', 25)) 100 92 101 self.assertEqual s(93 self.assertEqual( 102 94 scanstring('["Bad value", truth]', 2, None, True), 103 95 (u'Bad value', 12)) 104 96 105 97 def test_issue3623(self): 106 self.assertRaises(ValueError, json.decoder.scanstring, b"xxx", 1,98 self.assertRaises(ValueError, self.json.decoder.scanstring, b"xxx", 1, 107 99 "xxx") 108 100 self.assertRaises(UnicodeDecodeError, 109 json.encoder.encode_basestring_ascii, b"xx\xff") 101 self.json.encoder.encode_basestring_ascii, b"xx\xff") 102 103 def test_overflow(self): 104 with self.assertRaises(OverflowError): 105 self.json.decoder.scanstring(b"xxx", sys.maxsize+1) 106 107 108 class TestPyScanstring(TestScanstring, PyTest): pass 109 class TestCScanstring(TestScanstring, CTest): pass -
python/trunk/Lib/json/tests/test_separators.py
r2 r391 1 1 import textwrap 2 from unittest import TestCase 3 4 import json 2 from json.tests import PyTest, CTest 5 3 6 4 7 class TestSeparators( TestCase):5 class TestSeparators(object): 8 6 def test_separators(self): 9 7 h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', … … 32 30 33 31 34 d1 = json.dumps(h)35 d2 = json.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : '))32 d1 = self.dumps(h) 33 d2 = self.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : ')) 36 34 37 h1 = json.loads(d1)38 h2 = json.loads(d2)35 h1 = self.loads(d1) 36 h2 = self.loads(d2) 39 37 40 self.assertEquals(h1, h) 41 self.assertEquals(h2, h) 42 self.assertEquals(d2, expect) 38 self.assertEqual(h1, h) 39 self.assertEqual(h2, h) 40 self.assertEqual(d2, expect) 41 42 43 class TestPySeparators(TestSeparators, PyTest): pass 44 class TestCSeparators(TestSeparators, CTest): pass -
python/trunk/Lib/json/tests/test_speedups.py
r2 r391 1 import decimal 2 from unittest import TestCase 1 from json.tests import CTest 3 2 4 from json import decoder5 from json import encoder6 3 7 class TestSpeedups( TestCase):4 class TestSpeedups(CTest): 8 5 def test_scanstring(self): 9 self.assertEqual s(decoder.scanstring.__module__, "_json")10 self.assert _(decoder.scanstring isdecoder.c_scanstring)6 self.assertEqual(self.json.decoder.scanstring.__module__, "_json") 7 self.assertIs(self.json.decoder.scanstring, self.json.decoder.c_scanstring) 11 8 12 9 def test_encode_basestring_ascii(self): 13 self.assertEquals(encoder.encode_basestring_ascii.__module__, "_json") 14 self.assert_(encoder.encode_basestring_ascii is 15 encoder.c_encode_basestring_ascii) 10 self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, 11 "_json") 12 self.assertIs(self.json.encoder.encode_basestring_ascii, 13 self.json.encoder.c_encode_basestring_ascii) 14 15 class TestDecode(CTest): 16 def test_make_scanner(self): 17 self.assertRaises(AttributeError, self.json.scanner.c_make_scanner, 1) 18 19 def test_make_encoder(self): 20 self.assertRaises(TypeError, self.json.encoder.c_make_encoder, 21 None, 22 "\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75", 23 None) -
python/trunk/Lib/json/tests/test_unicode.py
r2 r391 1 from unittest import TestCase 1 from collections import OrderedDict 2 from json.tests import PyTest, CTest 2 3 3 import json4 4 5 class TestUnicode( TestCase):5 class TestUnicode(object): 6 6 def test_encoding1(self): 7 encoder = json.JSONEncoder(encoding='utf-8')7 encoder = self.json.JSONEncoder(encoding='utf-8') 8 8 u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' 9 9 s = u.encode('utf-8') 10 10 ju = encoder.encode(u) 11 11 js = encoder.encode(s) 12 self.assertEqual s(ju, js)12 self.assertEqual(ju, js) 13 13 14 14 def test_encoding2(self): 15 15 u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' 16 16 s = u.encode('utf-8') 17 ju = json.dumps(u, encoding='utf-8')18 js = json.dumps(s, encoding='utf-8')19 self.assertEqual s(ju, js)17 ju = self.dumps(u, encoding='utf-8') 18 js = self.dumps(s, encoding='utf-8') 19 self.assertEqual(ju, js) 20 20 21 21 def test_encoding3(self): 22 22 u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' 23 j = json.dumps(u)24 self.assertEqual s(j, '"\\u03b1\\u03a9"')23 j = self.dumps(u) 24 self.assertEqual(j, '"\\u03b1\\u03a9"') 25 25 26 26 def test_encoding4(self): 27 27 u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' 28 j = json.dumps([u])29 self.assertEqual s(j, '["\\u03b1\\u03a9"]')28 j = self.dumps([u]) 29 self.assertEqual(j, '["\\u03b1\\u03a9"]') 30 30 31 31 def test_encoding5(self): 32 32 u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' 33 j = json.dumps(u, ensure_ascii=False)34 self.assertEqual s(j, u'"{0}"'.format(u))33 j = self.dumps(u, ensure_ascii=False) 34 self.assertEqual(j, u'"{0}"'.format(u)) 35 35 36 36 def test_encoding6(self): 37 37 u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' 38 j = json.dumps([u], ensure_ascii=False)39 self.assertEqual s(j, u'["{0}"]'.format(u))38 j = self.dumps([u], ensure_ascii=False) 39 self.assertEqual(j, u'["{0}"]'.format(u)) 40 40 41 41 def test_big_unicode_encode(self): 42 42 u = u'\U0001d120' 43 self.assertEqual s(json.dumps(u), '"\\ud834\\udd20"')44 self.assertEqual s(json.dumps(u, ensure_ascii=False), u'"\U0001d120"')43 self.assertEqual(self.dumps(u), '"\\ud834\\udd20"') 44 self.assertEqual(self.dumps(u, ensure_ascii=False), u'"\U0001d120"') 45 45 46 46 def test_big_unicode_decode(self): 47 47 u = u'z\U0001d120x' 48 self.assertEqual s(json.loads('"' + u + '"'), u)49 self.assertEqual s(json.loads('"z\\ud834\\udd20x"'), u)48 self.assertEqual(self.loads('"' + u + '"'), u) 49 self.assertEqual(self.loads('"z\\ud834\\udd20x"'), u) 50 50 51 51 def test_unicode_decode(self): 52 52 for i in range(0, 0xd7ff): 53 53 u = unichr(i) 54 js = '"\\u{0:04x}"'.format(i) 55 self.assertEquals(json.loads(js), u) 54 s = '"\\u{0:04x}"'.format(i) 55 self.assertEqual(self.loads(s), u) 56 57 def test_object_pairs_hook_with_unicode(self): 58 s = u'{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' 59 p = [(u"xkd", 1), (u"kcw", 2), (u"art", 3), (u"hxm", 4), 60 (u"qrt", 5), (u"pad", 6), (u"hoy", 7)] 61 self.assertEqual(self.loads(s), eval(s)) 62 self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p) 63 od = self.loads(s, object_pairs_hook = OrderedDict) 64 self.assertEqual(od, OrderedDict(p)) 65 self.assertEqual(type(od), OrderedDict) 66 # the object_pairs_hook takes priority over the object_hook 67 self.assertEqual(self.loads(s, 68 object_pairs_hook = OrderedDict, 69 object_hook = lambda x: None), 70 OrderedDict(p)) 71 72 def test_default_encoding(self): 73 self.assertEqual(self.loads(u'{"a": "\xe9"}'.encode('utf-8')), 74 {'a': u'\xe9'}) 75 76 def test_unicode_preservation(self): 77 self.assertEqual(type(self.loads(u'""')), unicode) 78 self.assertEqual(type(self.loads(u'"a"')), unicode) 79 self.assertEqual(type(self.loads(u'["a"]')[0]), unicode) 80 # Issue 10038. 81 self.assertEqual(type(self.loads('"foo"')), unicode) 82 83 def test_bad_encoding(self): 84 self.assertRaises(UnicodeEncodeError, self.loads, '"a"', u"rat\xe9") 85 self.assertRaises(TypeError, self.loads, '"a"', 1) 86 87 88 class TestPyUnicode(TestUnicode, PyTest): pass 89 class TestCUnicode(TestUnicode, CTest): pass -
python/trunk/Lib/json/tool.py
r2 r391 3 3 Usage:: 4 4 5 $ echo '{"json":"obj"}' | python -m json.tool5 $ echo '{"json":"obj"}' | python -m json.tool 6 6 { 7 7 "json": "obj" 8 8 } 9 $ echo '{ 1.2:3.4}' | python -m json.tool10 Expecting property name : line 1 column 2(char 2)9 $ echo '{ 1.2:3.4}' | python -m json.tool 10 Expecting property name enclosed in double quotes: line 1 column 3 (char 2) 11 11 12 12 """ … … 25 25 outfile = open(sys.argv[2], 'wb') 26 26 else: 27 raise SystemExit("{0} [infile [outfile]]".format(sys.argv[0])) 28 try: 29 obj = json.load(infile) 30 except ValueError, e: 31 raise SystemExit(e) 32 json.dump(obj, outfile, sort_keys=True, indent=4) 33 outfile.write('\n') 27 raise SystemExit(sys.argv[0] + " [infile [outfile]]") 28 with infile: 29 try: 30 obj = json.load(infile) 31 except ValueError, e: 32 raise SystemExit(e) 33 with outfile: 34 json.dump(obj, outfile, sort_keys=True, 35 indent=4, separators=(',', ': ')) 36 outfile.write('\n') 34 37 35 38
Note:
See TracChangeset
for help on using the changeset viewer.