Project

General

Profile

Statistics
| Branch: | Revision:

root / env / lib / python2.7 / site-packages / django / core / serializers / json.py @ 1a305335

History | View | Annotate | Download (2.47 KB)

1
"""
2
Serialize data to/from JSON
3
"""
4

    
5
import datetime
6
import decimal
7
from StringIO import StringIO
8

    
9
from django.core.serializers.base import DeserializationError
10
from django.core.serializers.python import Serializer as PythonSerializer
11
from django.core.serializers.python import Deserializer as PythonDeserializer
12
from django.utils import simplejson
13
from django.utils.timezone import is_aware
14

    
15
class Serializer(PythonSerializer):
16
    """
17
    Convert a queryset to JSON.
18
    """
19
    internal_use_only = False
20

    
21
    def end_serialization(self):
22
        if simplejson.__version__.split('.') >= ['2', '1', '3']:
23
            # Use JS strings to represent Python Decimal instances (ticket #16850)
24
            self.options.update({'use_decimal': False})
25
        simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)
26

    
27
    def getvalue(self):
28
        if callable(getattr(self.stream, 'getvalue', None)):
29
            return self.stream.getvalue()
30

    
31

    
32
def Deserializer(stream_or_string, **options):
33
    """
34
    Deserialize a stream or string of JSON data.
35
    """
36
    if isinstance(stream_or_string, basestring):
37
        stream = StringIO(stream_or_string)
38
    else:
39
        stream = stream_or_string
40
    try:
41
        for obj in PythonDeserializer(simplejson.load(stream), **options):
42
            yield obj
43
    except GeneratorExit:
44
        raise
45
    except Exception, e:
46
        # Map to deserializer error
47
        raise DeserializationError(e)
48

    
49

    
50
class DjangoJSONEncoder(simplejson.JSONEncoder):
51
    """
52
    JSONEncoder subclass that knows how to encode date/time and decimal types.
53
    """
54
    def default(self, o):
55
        # See "Date Time String Format" in the ECMA-262 specification.
56
        if isinstance(o, datetime.datetime):
57
            r = o.isoformat()
58
            if o.microsecond:
59
                r = r[:23] + r[26:]
60
            if r.endswith('+00:00'):
61
                r = r[:-6] + 'Z'
62
            return r
63
        elif isinstance(o, datetime.date):
64
            return o.isoformat()
65
        elif isinstance(o, datetime.time):
66
            if is_aware(o):
67
                raise ValueError("JSON can't represent timezone-aware times.")
68
            r = o.isoformat()
69
            if o.microsecond:
70
                r = r[:12]
71
            return r
72
        elif isinstance(o, decimal.Decimal):
73
            return str(o)
74
        else:
75
            return super(DjangoJSONEncoder, self).default(o)
76

    
77
# Older, deprecated class name (for backwards compatibility purposes).
78
DateTimeAwareJSONEncoder = DjangoJSONEncoder
79