""" Serialize data to/from JSON """ # Avoid shadowing the standard library json module from __future__ import absolute_import import datetime import decimal import json from io import BytesIO 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.timezone import is_aware class Serializer(PythonSerializer): """ Convert a queryset to JSON. """ internal_use_only = False def end_serialization(self): if json.__version__.split('.') >= ['2', '1', '3']: # Use JS strings to represent Python Decimal instances (ticket #16850) self.options.update({'use_decimal': False}) json.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 = BytesIO(stream_or_string) else: stream = stream_or_string try: for obj in PythonDeserializer(json.load(stream), **options): yield obj except GeneratorExit: raise except Exception as e: # Map to deserializer error raise DeserializationError(e) class DjangoJSONEncoder(json.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