Given a Django model with a JSONField, what is the correct way of serializing and deserializing it using Django Rest Framework?
I\'ve already tried crating a custom
serializers.WritableField is deprecated. This works:
from rest_framework import serializers
from website.models import Picture
class PictureSerializer(serializers.HyperlinkedModelSerializer):
json = serializers.SerializerMethodField('clean_json')
class Meta:
model = Picture
fields = ('id', 'json')
def clean_json(self, obj):
return obj.json
If you're using Django Rest Framework >= 3.3, then the JSONField serializer is now included. This is now the correct way.
If you're using Django Rest Framework < 3.0, then see gzerone's answer.
If you're using DRF 3.0 - 3.2 AND you can't upgrade AND you don't need to serialize binary data, then follow these instructions.
First declare a field class:
from rest_framework import serializers
class JSONSerializerField(serializers.Field):
""" Serializer for JSONField -- required to make field writable"""
def to_internal_value(self, data):
return data
def to_representation(self, value):
return value
And then add in the field into the model like
class MySerializer(serializers.ModelSerializer):
json_data = JSONSerializerField()
And, if you do need to serialize binary data, you can always the copy official release code
In 2.4.x:
from rest_framework import serializers # get from https://gist.github.com/rouge8/5445149
class WritableJSONField(serializers.WritableField):
def to_native(self, obj):
return obj
class MyModelSerializer(serializers.HyperlinkedModelSerializer):
my_json_field = WritableJSONField() # you need this.
For the record, this "just works" now if you are using PostgreSQL, and your model field is adjango.contrib.postgres.JSONField.
I'm on PostgreSQL 9.4, Django 1.9, and Django REST Framework 3.3.2.
I have previously used several of the other solutions listed here, but was able to delete that extra code.
Example Model:
class Account(models.Model):
id = UUIDField(primary_key=True, default=uuid_nodash)
data = JSONField(blank=True, default="")
Example Serializer:
class AccountSerializer(BaseSerializer):
id = serializers.CharField()
class Meta:
model = Account
fields = ('id','data')
Example View:
class AccountViewSet(
viewsets.GenericViewSet,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin
):
model = Account
queryset = Account.objects.all()
serializer_class = AccountSerializer
filter_fields = ['id', 'data']
Mark Chackerian script didn't work for me, I'd to force the json transform:
import json
class JSONSerializerField(serializers.Field):
""" Serializer for JSONField -- required to make field writable"""
def to_internal_value(self, data):
json_data = {}
try:
json_data = json.loads(data)
except ValueError, e:
pass
finally:
return json_data
def to_representation(self, value):
return value
Works fine. Using DRF 3.15 and JSONFields in Django 1.8