Django Rest Framework and JSONField
Solution 1
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
Solution 2
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.
Solution 3
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
Solution 4
If and only if you know the first-level style of your JSON content (List or Dict), you can use DRF builtin DictField or ListField.
Ex:
class MyModelSerializer(serializers.HyperlinkedModelSerializer):
my_json_field = serializers.DictField()
It works fine, with GET/PUT/PATCH/POST
, including with nested contents.
Solution 5
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
Tzach
Updated on February 07, 2020Comments
-
Tzach about 4 years
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
and overridingto_native
andfrom_native
:from json_field.fields import JSONEncoder, JSONDecoder from rest_framework import serializers class JSONFieldSerializer(serializers.WritableField): def to_native(self, obj): return json.dumps(obj, cls = JSONEncoder) def from_native(self, data): return json.loads(data, cls = JSONDecoder)
But when I try to updating the model using
partial=True
, all the floats in the JSONField objects become strings. -
fixmycode over 9 yearsI'd recommend not using JSONField as the classname because it would clash with the other class.
-
gzerone over 9 yearsfixmycode, thanks for your suggestion on the classname. Hmm..., that just a sample code, which copied from gist.github.com/rouge8/5445149, so you can change it whatever you want. But @Tzach, 'JSONFieldSerializer' is not a suitable name for the subclass of the 'serializers.WritableField' I think. It looks like that JSONFieldSerializer and MyModelSerializer are the same things. Hope to hear your opinion.
-
Tzach over 9 yearsThanks @gzerone for your comment. I admit I didn't put too much attention for the new class name. Just wanted it not to cause clashes. Does
JSONWritableField
sounds better to you? -
gzerone over 9 yearsOr WritableJSONField, ;)
-
David Dehghan over 9 yearsYes. If you have an object that you want to serialize you just need to read it. This will not modify the original object that you are serializing.
-
mhsmith about 9 yearsThis is only valid for Django Rest Framework version 2. For version 3, see the answer by Mark Chackerian.
-
spacediver over 8 yearsAnd how you integrate this serializer field with model's JSONFields? Do you use ModelSerializer?
-
gzerone over 8 yearsYea, since Django 1.8 & DRF 3.x, I replaced WritableJSONField with ListField or DictField in my case, which works fine with postgres array fields.
-
jonalvarezz over 8 yearsI use
serializers.Serializer
, but withModelSerializer
should works too -
Beau over 8 yearsNoting that this does work with a
ModelSerializer
with DRF 3.2. -
Scott Smith over 8 yearsNone of the above worked for me, but this one did. Strange it is low on the list. On the client side I had to pass { "field": JSON.stringify(data), ... } with PATCH. Default jquery $.ajax calls broke out every value into long keys like "field[key1][key2][etc]": value.