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
To serialize a data from a request you can use the serializers.ModelSerializer
serializers.py
from rest_framwork import serializers
class FinalSerializer(serializers.ModelSerializer):
class Meta:
model=Student
fields='__all__'
views.py
import io
from yourappname.serializers import FinalSerializer #replace your app name
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser,MultiPartParser,FormParser
from rest_framework.response import Response
class DataList(APIView):
parser_classes = (JSONParser,MultiPartParser,FormParser) #If you are using postman
renderer_classes = (JSONRenderer,)
#Serialize
def get(self,request,format=None):
all_data=Student.objects.all()
serializer=FinalSerializer(all_data,many=True)
return Response(serializer.data)#Will return serialized json data,makes sure you have data in your model
#Deserialize
#Not tried this function but it will work
#from django documentation
def djson(self,request,format=None):
stream = io.BytesIO(json)
data = JSONParser().parse(stream)
serializer = FinalSerializer(data=data)
serializer.is_valid()
serializer.validated_data
If you want JSONField for mysql this is done in django-mysql and serializer was fixed some day ago [1], is not yet in any release.
[1] https://github.com/adamchainz/django-mysql/issues/353
add:
'django_mysql',
from django_mysql.models import JSONField
class Something(models.Model):
(...)
parameters = JSONField()
DRF gives us inbuilt field 'JSONField' for binary data, but JSON payload is verified only when you set 'binary' flag True then it convert into utf-8 and load the JSON payload, else it only treat them as string(if invalid json is sent) or json and validate both without error even though you cretaed JSONField
class JSONSerializer(serializers.ModelSerializer):
"""
serializer for JSON
"""
payload = serializers.JSONField(binary=True)
If you're using mysql (haven't tried with other databases), using both DRF's new JSONField
and Mark Chackerian's suggested JSONSerializerField
will save the json as a {u'foo': u'bar'}
string.
If you rather save it as {"foo": "bar"}
, this works for me:
import json
class JSONField(serializers.Field):
def to_representation(self, obj):
return json.loads(obj)
def to_internal_value(self, data):
return json.dumps(data)
Thanks by the help. This is the code i finally use for render it
class JSONSerializerField(serializers.Field):
"""Serializer for JSONField -- required to make field writable"""
def to_representation(self, value):
json_data = {}
try:
json_data = json.loads(value)
except ValueError as e:
raise e
finally:
return json_data
def to_internal_value(self, data):
return json.dumps(data)
class AnyModelSerializer(serializers.ModelSerializer):
field = JSONSerializerField()
class Meta:
model = SomeModel
fields = ('field',)
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.