Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/core/serializers/json.py: 27%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

83 statements  

1""" 

2Serialize data to/from JSON 

3""" 

4 

5import datetime 

6import decimal 

7import json 

8import uuid 

9 

10from django.core.serializers.base import DeserializationError 

11from django.core.serializers.python import Deserializer as PythonDeserializer 

12from django.core.serializers.python import Serializer as PythonSerializer 

13from django.utils.duration import duration_iso_string 

14from django.utils.functional import Promise 

15from django.utils.timezone import is_aware 

16 

17 

18class Serializer(PythonSerializer): 

19 """Convert a queryset to JSON.""" 

20 

21 internal_use_only = False 

22 

23 def _init_options(self): 

24 self._current = None 

25 self.json_kwargs = self.options.copy() 

26 self.json_kwargs.pop("stream", None) 

27 self.json_kwargs.pop("fields", None) 

28 if self.options.get("indent"): 

29 # Prevent trailing spaces 

30 self.json_kwargs["separators"] = (",", ": ") 

31 self.json_kwargs.setdefault("cls", DjangoJSONEncoder) 

32 self.json_kwargs.setdefault("ensure_ascii", False) 

33 

34 def start_serialization(self): 

35 self._init_options() 

36 self.stream.write("[") 

37 

38 def end_serialization(self): 

39 if self.options.get("indent"): 

40 self.stream.write("\n") 

41 self.stream.write("]") 

42 if self.options.get("indent"): 

43 self.stream.write("\n") 

44 

45 def end_object(self, obj): 

46 # self._current has the field data 

47 indent = self.options.get("indent") 

48 if not self.first: 

49 self.stream.write(",") 

50 if not indent: 

51 self.stream.write(" ") 

52 if indent: 

53 self.stream.write("\n") 

54 json.dump(self.get_dump_object(obj), self.stream, **self.json_kwargs) 

55 self._current = None 

56 

57 def getvalue(self): 

58 # Grandparent super 

59 return super(PythonSerializer, self).getvalue() 

60 

61 

62class Deserializer(PythonDeserializer): 

63 """Deserialize a stream or string of JSON data.""" 

64 

65 def __init__(self, stream_or_string, **options): 

66 if not isinstance(stream_or_string, (bytes, str)): 

67 stream_or_string = stream_or_string.read() 

68 if isinstance(stream_or_string, bytes): 

69 stream_or_string = stream_or_string.decode() 

70 try: 

71 objects = json.loads(stream_or_string) 

72 except Exception as exc: 

73 raise DeserializationError() from exc 

74 super().__init__(objects, **options) 

75 

76 def _handle_object(self, obj): 

77 try: 

78 yield from super()._handle_object(obj) 

79 except (GeneratorExit, DeserializationError): 

80 raise 

81 except Exception as exc: 

82 raise DeserializationError(f"Error deserializing object: {exc}") from exc 

83 

84 

85class DjangoJSONEncoder(json.JSONEncoder): 

86 """ 

87 JSONEncoder subclass that knows how to encode date/time, decimal types, and 

88 UUIDs. 

89 """ 

90 

91 def default(self, o): 

92 # See "Date Time String Format" in the ECMA-262 specification. 

93 if isinstance(o, datetime.datetime): 

94 r = o.isoformat() 

95 if o.microsecond: 

96 r = r[:23] + r[26:] 

97 if r.endswith("+00:00"): 

98 r = r.removesuffix("+00:00") + "Z" 

99 return r 

100 elif isinstance(o, datetime.date): 

101 return o.isoformat() 

102 elif isinstance(o, datetime.time): 

103 if is_aware(o): 

104 raise ValueError("JSON can't represent timezone-aware times.") 

105 r = o.isoformat() 

106 if o.microsecond: 

107 r = r[:12] 

108 return r 

109 elif isinstance(o, datetime.timedelta): 

110 return duration_iso_string(o) 

111 elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)): 

112 return str(o) 

113 else: 

114 return super().default(o)