Permalink
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
Cannot retrieve contributors at this time.
Cannot retrieve contributors at this time
| """ | |
| Serialize data to/from JSON | |
| """ | |
| import datetime | |
| import decimal | |
| import json | |
| import uuid | |
| from django.core.serializers.base import DeserializationError | |
| from django.core.serializers.python import ( | |
| Deserializer as PythonDeserializer, Serializer as PythonSerializer, | |
| ) | |
| from django.utils.duration import duration_iso_string | |
| from django.utils.functional import Promise | |
| from django.utils.timezone import is_aware | |
| class Serializer(PythonSerializer): | |
| """Convert a queryset to JSON.""" | |
| internal_use_only = False | |
| def _init_options(self): | |
| self._current = None | |
| self.json_kwargs = self.options.copy() | |
| self.json_kwargs.pop('stream', None) | |
| self.json_kwargs.pop('fields', None) | |
| if self.options.get('indent'): | |
| # Prevent trailing spaces | |
| self.json_kwargs['separators'] = (',', ': ') | |
| self.json_kwargs.setdefault('cls', DjangoJSONEncoder) | |
| def start_serialization(self): | |
| self._init_options() | |
| self.stream.write("[") | |
| def end_serialization(self): | |
| if self.options.get("indent"): | |
| self.stream.write("\n") | |
| self.stream.write("]") | |
| if self.options.get("indent"): | |
| self.stream.write("\n") | |
| def end_object(self, obj): | |
| # self._current has the field data | |
| indent = self.options.get("indent") | |
| if not self.first: | |
| self.stream.write(",") | |
| if not indent: | |
| self.stream.write(" ") | |
| if indent: | |
| self.stream.write("\n") | |
| json.dump(self.get_dump_object(obj), self.stream, **self.json_kwargs) | |
| self._current = None | |
| def getvalue(self): | |
| # Grandparent super | |
| return super(PythonSerializer, self).getvalue() | |
| def Deserializer(stream_or_string, **options): | |
| """Deserialize a stream or string of JSON data.""" | |
| if not isinstance(stream_or_string, (bytes, str)): | |
| stream_or_string = stream_or_string.read() | |
| if isinstance(stream_or_string, bytes): | |
| stream_or_string = stream_or_string.decode() | |
| try: | |
| objects = json.loads(stream_or_string) | |
| yield from PythonDeserializer(objects, **options) | |
| except (GeneratorExit, DeserializationError): | |
| raise | |
| except Exception as exc: | |
| raise DeserializationError() from exc | |
| class DjangoJSONEncoder(json.JSONEncoder): | |
| """ | |
| JSONEncoder subclass that knows how to encode date/time, decimal types, and | |
| UUIDs. | |
| """ | |
| 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, datetime.timedelta): | |
| return duration_iso_string(o) | |
| elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)): | |
| return str(o) | |
| else: | |
| return super().default(o) |