Ticket #3320: simplejson_1_5_new.diff

File simplejson_1_5_new.diff, 12.4 KB (added by LawrenceOluyede <l.oluyede@…>, 17 years ago)
  • django/utils/simplejson/LICENSE.txt

     
    1 simplejson 1.3
    21Copyright (c) 2006 Bob Ippolito
    32
    43Permission is hereby granted, free of charge, to any person obtaining a copy of
  • django/utils/simplejson/scanner.py

     
    33"""
    44import sre_parse, sre_compile, sre_constants
    55from sre_constants import BRANCH, SUBPATTERN
     6from re import VERBOSE, MULTILINE, DOTALL
    67import re
    78
    89__all__ = ['Scanner', 'pattern']
    910
    10 FLAGS = (re.VERBOSE | re.MULTILINE | re.DOTALL)
     11FLAGS = (VERBOSE | MULTILINE | DOTALL)
    1112class Scanner(object):
    1213    def __init__(self, lexicon, flags=FLAGS):
    1314        self.actions = [None]
  • django/utils/simplejson/__init__.py

     
    2727    >>> io.getvalue()
    2828    '["streaming API"]'
    2929
     30Compact 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
     36Pretty 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
    3045Decoding JSON::
    3146   
    3247    >>> import simplejson
     
    6883    ['[', '2.0', ', ', '1.0', ']']
    6984   
    7085
    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.
     86Note that the JSON produced by this module's default settings
     87is a subset of YAML, so it may be used as a serializer for that as well.
    7388"""
    74 __version__ = '1.3'
     89__version__ = '1.5'
    7590__all__ = [
    7691    'dump', 'dumps', 'load', 'loads',
    7792    'JSONDecoder', 'JSONEncoder',
     
    8196from django.utils.simplejson.encoder import JSONEncoder
    8297
    8398def 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):
    85100    """
    86101    Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
    87102    ``.write()``-supporting file-like object).
     
    105120    in strict compliance of the JSON specification, instead of using the
    106121    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
    107122
     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
    108127    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
    109128    ``.default()`` method to serialize additional types), specify it with
    110129    the ``cls`` kwarg.
     
    112131    if cls is None:
    113132        cls = JSONEncoder
    114133    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,
    116135        **kw).iterencode(obj)
    117136    # could accelerate with writelines in some versions of Python, at
    118137    # a debuggability cost
     
    120139        fp.write(chunk)
    121140
    122141def 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):
    124143    """
    125144    Serialize ``obj`` to a JSON formatted ``str``.
    126145
     
    141160    strict compliance of the JSON specification, instead of using the
    142161    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
    143162
     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
    144172    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
    145173    ``.default()`` method to serialize additional types), specify it with
    146174    the ``cls`` kwarg.
    147175    """
    148176    if cls is None:
    149177        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)
    152183
    153184def load(fp, encoding=None, cls=None, object_hook=None, **kw):
    154185    """
  • django/utils/simplejson/encoder.py

     
    33"""
    44import re
    55
    6 # this should match any kind of infinity
    7 INFCHARS = re.compile(r'[infINF]')
    86ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]')
    9 ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
     7ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])')
    108ESCAPE_DCT = {
     9    # escape all forward slashes to prevent </script> attack
     10    '/': '\\/',
    1111    '\\': '\\\\',
    1212    '"': '\\"',
    1313    '\b': '\\b',
     
    1616    '\r': '\\r',
    1717    '\t': '\\t',
    1818}
    19 for i in range(20):
     19for i in range(0x20):
    2020    ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
    2121
     22# assume this produces an infinity on all machines (probably not guaranteed)
     23INFINITY = float('1e66666')
     24
    2225def 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:
    2839        raise ValueError("Out of range float values are not JSON compliant: %r"
    2940            % (o,))
    30     # These are the string representations on the platforms I've tried
    31     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 everything
    38     if o != o or o == 0.0:
    39         return 'NaN'
    40     # Last ditch effort, assume inf
    41     if o < 0:
    42         return '-Infinity'
    43     return 'Infinity'
    4441
     42    return text
     43
     44
    4545def encode_basestring(s):
    4646    """
    4747    Return a JSON representation of a Python string
     
    9090    implementation (to raise ``TypeError``).
    9191    """
    9292    __all__ = ['__init__', 'default', 'encode', 'iterencode']
     93    item_separator = ', '
     94    key_separator = ': '
    9395    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):
    9598        """
    9699        Constructor for JSONEncoder, with sensible defaults.
    97100
     
    116119        If sort_keys is True, then the output of dictionaries will be
    117120        sorted by key; this is useful for regression tests to ensure
    118121        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.
    119131        """
    120132
    121133        self.skipkeys = skipkeys
     
    123135        self.check_circular = check_circular
    124136        self.allow_nan = allow_nan
    125137        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
    126142
     143    def _newline_indent(self):
     144        return '\n' + (' ' * (self.indent * self.current_indent_level))
     145
    127146    def _iterencode_list(self, lst, markers=None):
    128147        if not lst:
    129148            yield '[]'
     
    134153                raise ValueError("Circular reference detected")
    135154            markers[markerid] = lst
    136155        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
    137164        first = True
    138165        for value in lst:
    139166            if first:
    140167                first = False
    141168            else:
    142                 yield ', '
     169                yield separator
    143170            for chunk in self._iterencode(value, markers):
    144171                yield chunk
     172        if newline_indent is not None:
     173            self.current_indent_level -= 1
     174            yield self._newline_indent()
    145175        yield ']'
    146176        if markers is not None:
    147177            del markers[markerid]
     
    156186                raise ValueError("Circular reference detected")
    157187            markers[markerid] = dct
    158188        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
    159198        first = True
    160199        if self.ensure_ascii:
    161200            encoder = encode_basestring_ascii
     
    165204        if self.sort_keys:
    166205            keys = dct.keys()
    167206            keys.sort()
    168             items = [(k,dct[k]) for k in keys]
     207            items = [(k, dct[k]) for k in keys]
    169208        else:
    170209            items = dct.iteritems()
    171210        for key, value in items:
     
    190229            if first:
    191230                first = False
    192231            else:
    193                 yield ', '
     232                yield item_separator
    194233            yield encoder(key)
    195             yield ': '
     234            yield key_separator
    196235            for chunk in self._iterencode(value, markers):
    197236                yield chunk
     237        if newline_indent is not None:
     238            self.current_indent_level -= 1
     239            yield self._newline_indent()
    198240        yield '}'
    199241        if markers is not None:
    200242            del markers[markerid]
  • django/utils/simplejson/decoder.py

     
    127127        raise ValueError(errmsg("Expecting property name", s, end))
    128128    end += 1
    129129    encoding = getattr(context, 'encoding', None)
     130    iterscan = JSONScanner.iterscan
    130131    while True:
    131132        key, end = scanstring(s, end, encoding)
    132133        end = _w(s, end).end()
     
    134135            raise ValueError(errmsg("Expecting : delimiter", s, end))
    135136        end = _w(s, end + 1).end()
    136137        try:
    137             value, end = JSONScanner.iterscan(s, idx=end).next()
     138            value, end = iterscan(s, idx=end, context=context).next()
    138139        except StopIteration:
    139140            raise ValueError(errmsg("Expecting object", s, end))
    140141        pairs[key] = value
     
    164165    nextchar = s[end:end + 1]
    165166    if nextchar == ']':
    166167        return values, end + 1
     168    iterscan = JSONScanner.iterscan
    167169    while True:
    168170        try:
    169             value, end = JSONScanner.iterscan(s, idx=end).next()
     171            value, end = iterscan(s, idx=end, context=context).next()
    170172        except StopIteration:
    171173            raise ValueError(errmsg("Expecting object", s, end))
    172174        values.append(value)
Back to Top