mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-22 17:47:04 +03:00
Allow JSONField encoder customization. (#6713)
This commit is contained in:
parent
afb678433b
commit
514033815d
|
@ -501,9 +501,10 @@ Note that the child field **must** be an instance of `CharField`, as the hstore
|
||||||
|
|
||||||
A field class that validates that the incoming data structure consists of valid JSON primitives. In its alternate binary mode, it will represent and validate JSON-encoded binary strings.
|
A field class that validates that the incoming data structure consists of valid JSON primitives. In its alternate binary mode, it will represent and validate JSON-encoded binary strings.
|
||||||
|
|
||||||
**Signature**: `JSONField(binary)`
|
**Signature**: `JSONField(binary, encoder)`
|
||||||
|
|
||||||
- `binary` - If set to `True` then the field will output and validate a JSON encoded string, rather than a primitive data structure. Defaults to `False`.
|
- `binary` - If set to `True` then the field will output and validate a JSON encoded string, rather than a primitive data structure. Defaults to `False`.
|
||||||
|
- `encoder` - Use this JSON encoder to serialize input object. Defaults to `None`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1746,6 +1746,7 @@ class JSONField(Field):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.binary = kwargs.pop('binary', False)
|
self.binary = kwargs.pop('binary', False)
|
||||||
|
self.encoder = kwargs.pop('encoder', None)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def get_value(self, dictionary):
|
def get_value(self, dictionary):
|
||||||
|
@ -1767,14 +1768,14 @@ class JSONField(Field):
|
||||||
data = data.decode()
|
data = data.decode()
|
||||||
return json.loads(data)
|
return json.loads(data)
|
||||||
else:
|
else:
|
||||||
json.dumps(data)
|
json.dumps(data, cls=self.encoder)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
self.fail('invalid')
|
self.fail('invalid')
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
if self.binary:
|
if self.binary:
|
||||||
value = json.dumps(value)
|
value = json.dumps(value, cls=self.encoder)
|
||||||
value = value.encode()
|
value = value.encode()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
@ -1232,6 +1232,11 @@ class ModelSerializer(Serializer):
|
||||||
# `allow_blank` is only valid for textual fields.
|
# `allow_blank` is only valid for textual fields.
|
||||||
field_kwargs.pop('allow_blank', None)
|
field_kwargs.pop('allow_blank', None)
|
||||||
|
|
||||||
|
if postgres_fields and isinstance(model_field, postgres_fields.JSONField):
|
||||||
|
# Populate the `encoder` argument of `JSONField` instances generated
|
||||||
|
# for the PostgreSQL specific `JSONField`.
|
||||||
|
field_kwargs['encoder'] = getattr(model_field, 'encoder', None)
|
||||||
|
|
||||||
if postgres_fields and isinstance(model_field, postgres_fields.ArrayField):
|
if postgres_fields and isinstance(model_field, postgres_fields.ArrayField):
|
||||||
# Populate the `child` argument on `ListField` instances generated
|
# Populate the `child` argument on `ListField` instances generated
|
||||||
# for the PostgreSQL specific `ArrayField`.
|
# for the PostgreSQL specific `ArrayField`.
|
||||||
|
|
|
@ -13,6 +13,7 @@ from collections import OrderedDict
|
||||||
import django
|
import django
|
||||||
import pytest
|
import pytest
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.core.validators import (
|
from django.core.validators import (
|
||||||
MaxValueValidator, MinLengthValidator, MinValueValidator
|
MaxValueValidator, MinLengthValidator, MinValueValidator
|
||||||
)
|
)
|
||||||
|
@ -452,15 +453,17 @@ class TestPosgresFieldsMapping(TestCase):
|
||||||
def test_json_field(self):
|
def test_json_field(self):
|
||||||
class JSONFieldModel(models.Model):
|
class JSONFieldModel(models.Model):
|
||||||
json_field = postgres_fields.JSONField()
|
json_field = postgres_fields.JSONField()
|
||||||
|
json_field_with_encoder = postgres_fields.JSONField(encoder=DjangoJSONEncoder)
|
||||||
|
|
||||||
class TestSerializer(serializers.ModelSerializer):
|
class TestSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = JSONFieldModel
|
model = JSONFieldModel
|
||||||
fields = ['json_field']
|
fields = ['json_field', 'json_field_with_encoder']
|
||||||
|
|
||||||
expected = dedent("""
|
expected = dedent("""
|
||||||
TestSerializer():
|
TestSerializer():
|
||||||
json_field = JSONField(style={'base_template': 'textarea.html'})
|
json_field = JSONField(encoder=None, style={'base_template': 'textarea.html'})
|
||||||
|
json_field_with_encoder = JSONField(encoder=<class 'django.core.serializers.json.DjangoJSONEncoder'>, style={'base_template': 'textarea.html'})
|
||||||
""")
|
""")
|
||||||
self.assertEqual(repr(TestSerializer()), expected)
|
self.assertEqual(repr(TestSerializer()), expected)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user