Django Rest框架和JSONField
给定一个带有JSONField的Django模型,使用Django Rest Framework序列化和反序列化的正确方法是什么?
我已经试过创build一个自定义的serializers.WritableField
并覆盖to_native
和from_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对象中的所有浮点数都变成了string。
如果您使用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
然后在模型中join像这样的字段
class MySerializer(serializers.ModelSerializer): json_data = JSONSerializerField()
而且,如果您确实需要序列化二进制数据,则可以随时复制正式版本代码
在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.
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
当且仅当您知道JSON内容的第一层样式(List或Dict)时,您可以使用DRF内置的DictField或ListField 。
例如:
class MyModelSerializer(serializers.HyperlinkedModelSerializer): my_json_field = serializers.DictField()
它工作正常,与GET/PUT/PATCH/POST
,包括嵌套的内容。
马克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
为了logging,如果您正在使用PostgreSQL,则此“正常工作”,并且您的模型字段是django.contrib.postgres.JSONField
。
我在PostgreSQL 9.4,Django 1.9和Django REST Framework 3.3.2。
我以前使用过这里列出的其他解决scheme,但能够删除额外的代码。
示例模型:
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']
如果你正在使用mysql(还没有尝试过使用其他数据库),使用DRF的新JSONField
和Mark Chackerianbuild议的JSONSerializerField
将把json保存为{u'foo': u'bar'}
string。 如果你把它保存为{"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)
如果你想为MySQL的JSONField,这是在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()