Ticket #3320: simplejson_1_5_new.diff
File simplejson_1_5_new.diff, 12.4 KB (added by , 18 years ago) |
---|
-
django/utils/simplejson/LICENSE.txt
1 simplejson 1.32 1 Copyright (c) 2006 Bob Ippolito 3 2 4 3 Permission is hereby granted, free of charge, to any person obtaining a copy of -
django/utils/simplejson/scanner.py
3 3 """ 4 4 import sre_parse, sre_compile, sre_constants 5 5 from sre_constants import BRANCH, SUBPATTERN 6 from re import VERBOSE, MULTILINE, DOTALL 6 7 import re 7 8 8 9 __all__ = ['Scanner', 'pattern'] 9 10 10 FLAGS = ( re.VERBOSE | re.MULTILINE | re.DOTALL)11 FLAGS = (VERBOSE | MULTILINE | DOTALL) 11 12 class Scanner(object): 12 13 def __init__(self, lexicon, flags=FLAGS): 13 14 self.actions = [None] -
django/utils/simplejson/__init__.py
27 27 >>> io.getvalue() 28 28 '["streaming API"]' 29 29 30 Compact encoding:: 31 32 >>> import simplejson 33 >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':')) 34 '[1,2,3,{"4":5,"6":7}]' 35 36 Pretty printing:: 37 38 >>> import simplejson 39 >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4) 40 { 41 "4": 5, 42 "6": 7 43 } 44 30 45 Decoding JSON:: 31 46 32 47 >>> import simplejson … … 68 83 ['[', '2.0', ', ', '1.0', ']'] 69 84 70 85 71 Note that the JSON produced by this module is a subset of YAML,72 so it may be used as a serializer for that as well.86 Note that the JSON produced by this module's default settings 87 is a subset of YAML, so it may be used as a serializer for that as well. 73 88 """ 74 __version__ = '1. 3'89 __version__ = '1.5' 75 90 __all__ = [ 76 91 'dump', 'dumps', 'load', 'loads', 77 92 'JSONDecoder', 'JSONEncoder', … … 81 96 from django.utils.simplejson.encoder import JSONEncoder 82 97 83 98 def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, 84 allow_nan=True, cls=None, **kw):99 allow_nan=True, cls=None, indent=None, **kw): 85 100 """ 86 101 Serialize ``obj`` as a JSON formatted stream to ``fp`` (a 87 102 ``.write()``-supporting file-like object). … … 105 120 in strict compliance of the JSON specification, instead of using the 106 121 JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). 107 122 123 If ``indent`` is a non-negative integer, then JSON array elements and object 124 members will be pretty-printed with that indent level. An indent level 125 of 0 will only insert newlines. ``None`` is the most compact representation. 126 108 127 To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the 109 128 ``.default()`` method to serialize additional types), specify it with 110 129 the ``cls`` kwarg. … … 112 131 if cls is None: 113 132 cls = JSONEncoder 114 133 iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, 115 check_circular=check_circular, allow_nan=allow_nan, 134 check_circular=check_circular, allow_nan=allow_nan, indent=indent, 116 135 **kw).iterencode(obj) 117 136 # could accelerate with writelines in some versions of Python, at 118 137 # a debuggability cost … … 120 139 fp.write(chunk) 121 140 122 141 def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, 123 allow_nan=True, cls=None, **kw):142 allow_nan=True, cls=None, indent=None, separators=None, **kw): 124 143 """ 125 144 Serialize ``obj`` to a JSON formatted ``str``. 126 145 … … 141 160 strict compliance of the JSON specification, instead of using the 142 161 JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). 143 162 163 If ``indent`` is a non-negative integer, then JSON array elements and 164 object members will be pretty-printed with that indent level. An indent 165 level of 0 will only insert newlines. ``None`` is the most compact 166 representation. 167 168 If ``separators`` is an ``(item_separator, dict_separator)`` tuple 169 then it will be used instead of the default ``(', ', ': ')`` separators. 170 ``(',', ':')`` is the most compact JSON representation. 171 144 172 To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the 145 173 ``.default()`` method to serialize additional types), specify it with 146 174 the ``cls`` kwarg. 147 175 """ 148 176 if cls is None: 149 177 cls = JSONEncoder 150 return cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, 151 check_circular=check_circular, allow_nan=allow_nan, **kw).encode(obj) 178 return cls( 179 skipkeys=skipkeys, ensure_ascii=ensure_ascii, 180 check_circular=check_circular, allow_nan=allow_nan, indent=indent, 181 separators=separators, 182 **kw).encode(obj) 152 183 153 184 def load(fp, encoding=None, cls=None, object_hook=None, **kw): 154 185 """ -
django/utils/simplejson/encoder.py
3 3 """ 4 4 import re 5 5 6 # this should match any kind of infinity7 INFCHARS = re.compile(r'[infINF]')8 6 ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]') 9 ESCAPE_ASCII = re.compile(r'([\\" ]|[^\ -~])')7 ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])') 10 8 ESCAPE_DCT = { 9 # escape all forward slashes to prevent </script> attack 10 '/': '\\/', 11 11 '\\': '\\\\', 12 12 '"': '\\"', 13 13 '\b': '\\b', … … 16 16 '\r': '\\r', 17 17 '\t': '\\t', 18 18 } 19 for i in range( 20):19 for i in range(0x20): 20 20 ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) 21 21 22 # assume this produces an infinity on all machines (probably not guaranteed) 23 INFINITY = float('1e66666') 24 22 25 def floatstr(o, allow_nan=True): 23 s = str(o) 24 # If the first non-sign is a digit then it's not a special value 25 if (o < 0.0 and s[1].isdigit()) or s[0].isdigit(): 26 return s 27 elif not allow_nan: 26 # Check for specials. Note that this type of test is processor- and/or 27 # platform-specific, so do tests which don't depend on the internals. 28 29 if o != o: 30 text = 'NaN' 31 elif o == INFINITY: 32 text = 'Infinity' 33 elif o == -INFINITY: 34 text = '-Infinity' 35 else: 36 return str(o) 37 38 if not allow_nan: 28 39 raise ValueError("Out of range float values are not JSON compliant: %r" 29 40 % (o,)) 30 # These are the string representations on the platforms I've tried31 if s == 'nan':32 return 'NaN'33 if s == 'inf':34 return 'Infinity'35 if s == '-inf':36 return '-Infinity'37 # NaN should either be inequal to itself, or equal to everything38 if o != o or o == 0.0:39 return 'NaN'40 # Last ditch effort, assume inf41 if o < 0:42 return '-Infinity'43 return 'Infinity'44 41 42 return text 43 44 45 45 def encode_basestring(s): 46 46 """ 47 47 Return a JSON representation of a Python string … … 90 90 implementation (to raise ``TypeError``). 91 91 """ 92 92 __all__ = ['__init__', 'default', 'encode', 'iterencode'] 93 item_separator = ', ' 94 key_separator = ': ' 93 95 def __init__(self, skipkeys=False, ensure_ascii=True, 94 check_circular=True, allow_nan=True, sort_keys=False): 96 check_circular=True, allow_nan=True, sort_keys=False, 97 indent=None, separators=None): 95 98 """ 96 99 Constructor for JSONEncoder, with sensible defaults. 97 100 … … 116 119 If sort_keys is True, then the output of dictionaries will be 117 120 sorted by key; this is useful for regression tests to ensure 118 121 that JSON serializations can be compared on a day-to-day basis. 122 123 If indent is a non-negative integer, then JSON array 124 elements and object members will be pretty-printed with that 125 indent level. An indent level of 0 will only insert newlines. 126 None is the most compact representation. 127 128 If specified, separators should be a (item_separator, key_separator) 129 tuple. The default is (', ', ': '). To get the most compact JSON 130 representation you should specify (',', ':') to eliminate whitespace. 119 131 """ 120 132 121 133 self.skipkeys = skipkeys … … 123 135 self.check_circular = check_circular 124 136 self.allow_nan = allow_nan 125 137 self.sort_keys = sort_keys 138 self.indent = indent 139 self.current_indent_level = 0 140 if separators is not None: 141 self.item_separator, self.key_separator = separators 126 142 143 def _newline_indent(self): 144 return '\n' + (' ' * (self.indent * self.current_indent_level)) 145 127 146 def _iterencode_list(self, lst, markers=None): 128 147 if not lst: 129 148 yield '[]' … … 134 153 raise ValueError("Circular reference detected") 135 154 markers[markerid] = lst 136 155 yield '[' 156 if self.indent is not None: 157 self.current_indent_level += 1 158 newline_indent = self._newline_indent() 159 separator = self.item_separator + newline_indent 160 yield newline_indent 161 else: 162 newline_indent = None 163 separator = self.item_separator 137 164 first = True 138 165 for value in lst: 139 166 if first: 140 167 first = False 141 168 else: 142 yield ', '169 yield separator 143 170 for chunk in self._iterencode(value, markers): 144 171 yield chunk 172 if newline_indent is not None: 173 self.current_indent_level -= 1 174 yield self._newline_indent() 145 175 yield ']' 146 176 if markers is not None: 147 177 del markers[markerid] … … 156 186 raise ValueError("Circular reference detected") 157 187 markers[markerid] = dct 158 188 yield '{' 189 key_separator = self.key_separator 190 if self.indent is not None: 191 self.current_indent_level += 1 192 newline_indent = self._newline_indent() 193 item_separator = self.item_separator + newline_indent 194 yield newline_indent 195 else: 196 newline_indent = None 197 item_separator = self.item_separator 159 198 first = True 160 199 if self.ensure_ascii: 161 200 encoder = encode_basestring_ascii … … 165 204 if self.sort_keys: 166 205 keys = dct.keys() 167 206 keys.sort() 168 items = [(k, dct[k]) for k in keys]207 items = [(k, dct[k]) for k in keys] 169 208 else: 170 209 items = dct.iteritems() 171 210 for key, value in items: … … 190 229 if first: 191 230 first = False 192 231 else: 193 yield ', '232 yield item_separator 194 233 yield encoder(key) 195 yield ': '234 yield key_separator 196 235 for chunk in self._iterencode(value, markers): 197 236 yield chunk 237 if newline_indent is not None: 238 self.current_indent_level -= 1 239 yield self._newline_indent() 198 240 yield '}' 199 241 if markers is not None: 200 242 del markers[markerid] -
django/utils/simplejson/decoder.py
127 127 raise ValueError(errmsg("Expecting property name", s, end)) 128 128 end += 1 129 129 encoding = getattr(context, 'encoding', None) 130 iterscan = JSONScanner.iterscan 130 131 while True: 131 132 key, end = scanstring(s, end, encoding) 132 133 end = _w(s, end).end() … … 134 135 raise ValueError(errmsg("Expecting : delimiter", s, end)) 135 136 end = _w(s, end + 1).end() 136 137 try: 137 value, end = JSONScanner.iterscan(s, idx=end).next()138 value, end = iterscan(s, idx=end, context=context).next() 138 139 except StopIteration: 139 140 raise ValueError(errmsg("Expecting object", s, end)) 140 141 pairs[key] = value … … 164 165 nextchar = s[end:end + 1] 165 166 if nextchar == ']': 166 167 return values, end + 1 168 iterscan = JSONScanner.iterscan 167 169 while True: 168 170 try: 169 value, end = JSONScanner.iterscan(s, idx=end).next()171 value, end = iterscan(s, idx=end, context=context).next() 170 172 except StopIteration: 171 173 raise ValueError(errmsg("Expecting object", s, end)) 172 174 values.append(value)