""" Serialize data to/from JSON """ import datetime import decimal from StringIO import StringIO from django.core.serializers.base import DeserializationError from django.core.serializers.python import Serializer as PythonSerializer from django.core.serializers.python import Deserializer as PythonDeserializer from django.utils import simplejson from django.utils.timezone import is_aware class Serializer(PythonSerializer): """ Convert a queryset to JSON. """ internal_use_only = False def end_serialization(self): if simplejson.__version__.split('.') >= ['2', '1', '3']: # Use JS strings to represent Python Decimal instances (ticket #16850) self.options.update({'use_decimal': False}) simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options) def getvalue(self): if callable(getattr(self.stream, 'getvalue', None)): return self.stream.getvalue() def Deserializer(stream_or_string, **options): """ Deserialize a stream or string of JSON data. """ if isinstance(stream_or_string, basestring): stream = StringIO(stream_or_string) else: stream = stream_or_string try: for obj in PythonDeserializer(simplejson.load(stream), **options): yield obj except GeneratorExit: raise except Exception, e: # Map to deserializer error raise DeserializationError(e) class DjangoJSONEncoder(simplejson.JSONEncoder): """ JSONEncoder subclass that knows how to encode date/time and decimal types. """ def default(self, o): # See "Date Time String Format" in the ECMA-262 specification. if isinstance(o, datetime.datetime): r = o.isoformat() if o.microsecond: r = r[:23] + r[26:] if r.endswith('+00:00'): r = r[:-6] + 'Z' return r elif isinstance(o, datetime.date): return o.isoformat() elif isinstance(o, datetime.time): if is_aware(o): raise ValueError("JSON can't represent timezone-aware times.") r = o.isoformat() if o.microsecond: r = r[:12] return r elif isinstance(o, decimal.Decimal): return str(o) else: return super(DjangoJSONEncoder, self).default(o) # Older, deprecated class name (for backwards compatibility purposes). DateTimeAwareJSONEncoder = DjangoJSONEncoder