Django Rest Framework和JSONField

时间:2014-03-16 08:57:23

标签: python django django-models django-rest-framework

给定带有JSONField的Django模型,使用Django Rest Framework对其进行序列化和反序列化的正确方法是什么?

我已经尝试过装箱自定义serializers.WritableField并覆盖to_nativefrom_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)

但是当我尝试使用partial=True更新模型时,JSONField对象中的所有浮点数都成为字符串。

11 个答案:

答案 0 :(得分:59)

如果您使用的是Django Rest Framework> = 3.3,则JSONField序列化程序为now included。现在这是正确的方法。

如果您正在使用Django Rest Framework< 3.0,然后看gzerone的答案。

如果您使用的是DRF 3.0 - 3.2并且无法升级,则无需序列化二进制数据,请按照这些说明进行操作。

首先声明一个字段类:

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

然后将字段添加到模型中,如

class MySerializer(serializers.ModelSerializer):
    json_data = JSONSerializerField()

而且,如果您确实需要序列化二进制数据,您可以随时复制official release code

答案 1 :(得分:18)

在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.

答案 2 :(得分:5)

serializers.WritableField已弃用。这有效:

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

答案 3 :(得分:4)

Mark Chackerian脚本对我不起作用,我强迫json转换:

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

工作正常。在Django 1.8中使用DRF 3.15和JSONFields

答案 4 :(得分:4)

当且仅当您知道JSON内容(列表或词典)的第一级样式时,您可以使用DRF内置DictFieldListField

前:

class MyModelSerializer(serializers.HyperlinkedModelSerializer):
    my_json_field = serializers.DictField()

使用GET/PUT/PATCH/POST工作正常,包括嵌套内容。

答案 5 :(得分:4)

对于记录,如果您正在使用PostgreSQL,那么这“正常”,您的模型字段为django.contrib.postgres.JSONField

我使用PostgreSQL 9.4,Django 1.9和Django REST Framework 3.3.2。

我以前使用过此处列出的其他几种解决方案,但能够删除这些额外的代码。

示例模型:

class Account(models.Model):
    id = UUIDField(primary_key=True, default=uuid_nodash)
    data = JSONField(blank=True, default="")

示例序列化程序:

class AccountSerializer(BaseSerializer):
    id = serializers.CharField()
    class Meta:
        model = Account
        fields = ('id','data')

示例视图:

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']

答案 6 :(得分:1)

如果您正在使用mysql(尚未尝试过其他数据库),则使用DRF的新JSONField和Mark Chackerian建议的JSONSerializerField将json保存为{u'foo': u'bar'}字符串。 如果您将其保存为{"foo": "bar"},这对我有用:

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)

答案 7 :(得分:1)

感谢您的帮助。这是我最终用于渲染它的代码

.sub-menu

答案 8 :(得分:1)

要序列化请求中的数据,可以使用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

答案 9 :(得分:0)

如果你想要jSONField for mysql这是在django-mysql中完成的,并且序列化器在前一天被修复了[1],还没有在任何版本中。

[1] https://github.com/adamchainz/django-mysql/issues/353

setting.py

添加:

    'django_mysql',

models.py

from django_mysql.models import JSONField

class Something(models.Model):
(...)
    parameters = JSONField()

答案 10 :(得分:0)

  

DRF为我们提供内置的JSONField'对于二进制数据,但是JSON   只有在您设置了二进制文件时才会验证有效负载。标志为True然后它转换为utf-8并加载JSON有效负载,否则它只   将它们视为字符串(如果发送了无效的json)或json并验证它们   即使您创建了JSONField

,也没有错误
class JSONSerializer(serializers.ModelSerializer):
    """
    serializer for JSON
    """
    payload = serializers.JSONField(binary=True)