Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

json.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """
  2. Serialize data to/from JSON
  3. """
  4. import datetime
  5. import decimal
  6. import json
  7. import uuid
  8. from django.core.serializers.base import DeserializationError
  9. from django.core.serializers.python import (
  10. Deserializer as PythonDeserializer, Serializer as PythonSerializer,
  11. )
  12. from django.utils.duration import duration_iso_string
  13. from django.utils.functional import Promise
  14. from django.utils.timezone import is_aware
  15. class Serializer(PythonSerializer):
  16. """Convert a queryset to JSON."""
  17. internal_use_only = False
  18. def _init_options(self):
  19. self._current = None
  20. self.json_kwargs = self.options.copy()
  21. self.json_kwargs.pop('stream', None)
  22. self.json_kwargs.pop('fields', None)
  23. if self.options.get('indent'):
  24. # Prevent trailing spaces
  25. self.json_kwargs['separators'] = (',', ': ')
  26. self.json_kwargs.setdefault('cls', DjangoJSONEncoder)
  27. def start_serialization(self):
  28. self._init_options()
  29. self.stream.write("[")
  30. def end_serialization(self):
  31. if self.options.get("indent"):
  32. self.stream.write("\n")
  33. self.stream.write("]")
  34. if self.options.get("indent"):
  35. self.stream.write("\n")
  36. def end_object(self, obj):
  37. # self._current has the field data
  38. indent = self.options.get("indent")
  39. if not self.first:
  40. self.stream.write(",")
  41. if not indent:
  42. self.stream.write(" ")
  43. if indent:
  44. self.stream.write("\n")
  45. json.dump(self.get_dump_object(obj), self.stream, **self.json_kwargs)
  46. self._current = None
  47. def getvalue(self):
  48. # Grandparent super
  49. return super(PythonSerializer, self).getvalue()
  50. def Deserializer(stream_or_string, **options):
  51. """Deserialize a stream or string of JSON data."""
  52. if not isinstance(stream_or_string, (bytes, str)):
  53. stream_or_string = stream_or_string.read()
  54. if isinstance(stream_or_string, bytes):
  55. stream_or_string = stream_or_string.decode()
  56. try:
  57. objects = json.loads(stream_or_string)
  58. yield from PythonDeserializer(objects, **options)
  59. except (GeneratorExit, DeserializationError):
  60. raise
  61. except Exception as exc:
  62. raise DeserializationError() from exc
  63. class DjangoJSONEncoder(json.JSONEncoder):
  64. """
  65. JSONEncoder subclass that knows how to encode date/time, decimal types, and
  66. UUIDs.
  67. """
  68. def default(self, o):
  69. # See "Date Time String Format" in the ECMA-262 specification.
  70. if isinstance(o, datetime.datetime):
  71. r = o.isoformat()
  72. if o.microsecond:
  73. r = r[:23] + r[26:]
  74. if r.endswith('+00:00'):
  75. r = r[:-6] + 'Z'
  76. return r
  77. elif isinstance(o, datetime.date):
  78. return o.isoformat()
  79. elif isinstance(o, datetime.time):
  80. if is_aware(o):
  81. raise ValueError("JSON can't represent timezone-aware times.")
  82. r = o.isoformat()
  83. if o.microsecond:
  84. r = r[:12]
  85. return r
  86. elif isinstance(o, datetime.timedelta):
  87. return duration_iso_string(o)
  88. elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
  89. return str(o)
  90. else:
  91. return super().default(o)