1# -*- coding: utf-8 -*- 2from django.utils.html import conditional_escape 3from django.utils.encoding import force_text 4from django.utils.functional import Promise 5from django.core.serializers.json import DjangoJSONEncoder 6from django.utils.six import iteritems 7 8 9class SafeJSONEncoder(DjangoJSONEncoder): 10 def _recursive_escape(self, o, esc=conditional_escape): 11 if isinstance(o, dict): 12 return type(o)((esc(k), self._recursive_escape(v)) for (k, v) in iteritems(o)) 13 if isinstance(o, (list, tuple)): 14 return type(o)(self._recursive_escape(v) for v in o) 15 if type(o) is bool: 16 return o 17 try: 18 return type(o)(esc(o)) 19 except (ValueError, TypeError): 20 return self.default(o) 21 22 def encode(self, o): 23 value = self._recursive_escape(o) 24 return super(SafeJSONEncoder, self).encode(value) 25 26 def default(self, o): 27 if isinstance(o, Promise): 28 return force_text(o) 29 return super(SafeJSONEncoder, self).default(o) 30