Django Rest Framework与JSONField

70 投票
11 回答
54968 浏览
提问于 2025-04-17 22:31

在Django模型中,如果有一个JSONField,那么使用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 个回答

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

这样做没问题。我使用的是 DRF 3.15 和 Django 1.8 中的 JSONFields。

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
6

只有当你知道你的JSON内容的第一层结构是列表(List)还是字典(Dict)时,你才能使用DRF自带的DictFieldListField

举个例子:

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

这样使用没问题,可以处理GET/PUT/PATCH/POST请求,包括处理嵌套的内容。

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

如果你使用的是 Django Rest Framework 版本大于等于 3.3,那么 JSONField 的序列化器现在已经包含在里面了。这个方法是正确的。

如果你使用的是 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()

如果你确实需要序列化二进制数据,你可以随时复制 官方发布的代码

撰写回答