Deep json serialization

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
goodjson.py: 

from django.core.serializers.json import DateTimeAwareJSONEncoder
from django.core import serializers
from django.db.models.query import QuerySet
from django.db.models import Model
from django.utils import simplejson
from django.core.serializers.python import Serializer as PythonSerializer#, Deserializer as PythonDeserializer
from django.utils.encoding import smart_unicode
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

class ModelAwareJSONEncoder(DateTimeAwareJSONEncoder):
    
    def __init__(self,select_related=False,include_unicode=False,**options):
        super(ModelAwareJSONEncoder,self).__init__(**options)
        self.select_related = select_related
        self.include_unicode = include_unicode
        
    def default(self, o):
        
        if self.select_related:
            serializer_name = 'goodpython'
        else:
            serializer_name = 'python'
        
        if isinstance(o, QuerySet):
            serializer = serializers.get_serializer(serializer_name)()
            serializer.include_unicode = self.include_unicode
            return serializer.serialize(o)
        if isinstance(o, Model):
            serializer = serializers.get_serializer(serializer_name)()
            serializer.include_unicode = self.include_unicode
            return serializer.serialize([o])[0]
        else:
            return super(ModelAwareJSONEncoder, self).default(o)
        
class Serializer(PythonSerializer):
    def serialize(self, object, **options):
        return simplejson.dumps(object, cls=ModelAwareJSONEncoder, **options)


goodpython.py:
from django.core.serializers.json import DateTimeAwareJSONEncoder
from django.core import serializers
from django.db.models.query import QuerySet
from django.db.models import Model
from django.utils import simplejson
from django.core.serializers.python import Serializer as PythonSerializer#, Deserializer as PythonDeserializer
from django.utils.encoding import smart_unicode
from django.template.defaultfilters import force_escape, escapejs, mark_safe
from core.libs.htmlfield import HtmlField
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

        
class Serializer(PythonSerializer):
    def end_object(self, obj):
        fields = self._current
        if hasattr(self,'include_unicode') and self.include_unicode:
            fields.update({'__unicode__': unicode(obj)})
        self.objects.append({
            "model"  : smart_unicode(obj._meta),
            "pk"     : smart_unicode(obj._get_pk_val(), strings_only=True),
            "fields" : fields
        })
        self._current = None

    def handle_fk_field(self, obj, field):
        related = getattr(obj, field.name)
        self._current[field.name] = self.serialize_related(related)

    def handle_m2m_field(self, obj, field):
        self._current[field.name] =  [self.serialize_related(related) for related in getattr(obj, field.name).iterator()]
        
    def handle_field(self, obj, field):
        ''' The std. serialization is not suitable for the fields containing HTML. If such JSON is being output inside an inline <script> tag, the javascript code become invalid. This is why we need escapejs function to be applied to the contents of such fields. But after that the result is being escaped one more time. So, you need to unescape the result in your javascript with unescapejs()
        '''
        if isinstance(field, HtmlField):
            self._current[field.name] = smart_unicode(escapejs(getattr(obj, field.name) or ''), strings_only=True)
        else:
            self._current[field.name] = smart_unicode(getattr(obj, field.name), strings_only=True)

    def serialize_related(self,related):
        if hasattr(self, 'already_serialized') and related in self.already_serialized:
            serializer = serializers.get_serializer('python')()
        else:
            if hasattr(self, 'already_serialized'):
                self.already_serialized.add(related)
            else:
                self.already_serialized = set([related])
            serializer = serializers.get_serializer('goodpython')()
            serializer.already_serialized = self.already_serialized 
        value = None
        serializer.include_unicode = self.include_unicode
        if isinstance(related, QuerySet):
            value = serializer.serialize(related,**self.options)
        if isinstance(related, Model):
            value = serializer.serialize([related],**self.options)[0]
        return value

More like this

  1. An alternative model serializer for django models by isaact 5 years, 5 months ago
  2. JSON serializer supporting natural primary keys by bdauvergne 3 weeks, 5 days ago
  3. Updated: GeoJSON Serializer for GeoDjango (gis) by danielsokolowski 2 years, 5 months ago
  4. GeoJSON Serializer for GeoDjango (gis) by danielsokolowski 2 years, 11 months ago
  5. Modelaware json serializer by fivethreeo 7 years, 1 month ago

Comments

jtheoof (on January 7, 2011):

What is HtmlField that you are talking about line 54?

#

(Forgotten your password?)