mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-05-26 01:03:12 +03:00
Added JSONField. Closes #3170.
This commit is contained in:
parent
bae47b7f36
commit
10dbf1316f
|
@ -459,6 +459,14 @@ You can also use the declarative style, as with `ListField`. For example:
|
||||||
class DocumentField(DictField):
|
class DocumentField(DictField):
|
||||||
child = CharField()
|
child = CharField()
|
||||||
|
|
||||||
|
## JSONField
|
||||||
|
|
||||||
|
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 strings.
|
||||||
|
|
||||||
|
**Signature**: `JSONField(binary)`
|
||||||
|
|
||||||
|
- `binary` - If set to `True` then the field will output and validate a JSON encoded string, rather that a primitive data structure. Defaults to `False`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Miscellaneous fields
|
# Miscellaneous fields
|
||||||
|
|
|
@ -64,6 +64,13 @@ except ImportError:
|
||||||
postgres_fields = None
|
postgres_fields = None
|
||||||
|
|
||||||
|
|
||||||
|
# JSONField is only supported from 1.9 onwards
|
||||||
|
try:
|
||||||
|
from django.contrib.postgres.fields import JSONField
|
||||||
|
except ImportError:
|
||||||
|
JSONField = None
|
||||||
|
|
||||||
|
|
||||||
# django-filter is optional
|
# django-filter is optional
|
||||||
try:
|
try:
|
||||||
import django_filters
|
import django_filters
|
||||||
|
|
|
@ -5,6 +5,7 @@ import copy
|
||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
import inspect
|
import inspect
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -1522,6 +1523,31 @@ class DictField(Field):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class JSONField(Field):
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _('Value must be valid JSON.')
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.binary = kwargs.pop('binary', False)
|
||||||
|
super(JSONField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
try:
|
||||||
|
if self.binary:
|
||||||
|
return json.loads(data)
|
||||||
|
else:
|
||||||
|
json.dumps(data)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
self.fail('invalid')
|
||||||
|
return data
|
||||||
|
|
||||||
|
def to_representation(self, value):
|
||||||
|
if self.binary:
|
||||||
|
return json.dumps(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
# Miscellaneous field types...
|
# Miscellaneous field types...
|
||||||
|
|
||||||
class ReadOnlyField(Field):
|
class ReadOnlyField(Field):
|
||||||
|
|
|
@ -21,6 +21,7 @@ from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from rest_framework.compat import DurationField as ModelDurationField
|
from rest_framework.compat import DurationField as ModelDurationField
|
||||||
|
from rest_framework.compat import JSONField as ModelJSONField
|
||||||
from rest_framework.compat import postgres_fields, unicode_to_repr
|
from rest_framework.compat import postgres_fields, unicode_to_repr
|
||||||
from rest_framework.utils import model_meta
|
from rest_framework.utils import model_meta
|
||||||
from rest_framework.utils.field_mapping import (
|
from rest_framework.utils.field_mapping import (
|
||||||
|
@ -790,6 +791,8 @@ class ModelSerializer(Serializer):
|
||||||
}
|
}
|
||||||
if ModelDurationField is not None:
|
if ModelDurationField is not None:
|
||||||
serializer_field_mapping[ModelDurationField] = DurationField
|
serializer_field_mapping[ModelDurationField] = DurationField
|
||||||
|
if ModelJSONField is not None:
|
||||||
|
serializer_field_mapping[ModelJSONField] = JSONField
|
||||||
serializer_related_field = PrimaryKeyRelatedField
|
serializer_related_field = PrimaryKeyRelatedField
|
||||||
serializer_url_field = HyperlinkedIdentityField
|
serializer_url_field = HyperlinkedIdentityField
|
||||||
serializer_choice_field = ChoiceField
|
serializer_choice_field = ChoiceField
|
||||||
|
|
|
@ -1525,6 +1525,62 @@ class TestUnvalidatedDictField(FieldValues):
|
||||||
field = serializers.DictField()
|
field = serializers.DictField()
|
||||||
|
|
||||||
|
|
||||||
|
class TestJSONField(FieldValues):
|
||||||
|
"""
|
||||||
|
Values for `JSONField`.
|
||||||
|
"""
|
||||||
|
valid_inputs = [
|
||||||
|
({
|
||||||
|
'a': 1,
|
||||||
|
'b': ['some', 'list', True, 1.23],
|
||||||
|
'3': None
|
||||||
|
}, {
|
||||||
|
'a': 1,
|
||||||
|
'b': ['some', 'list', True, 1.23],
|
||||||
|
'3': None
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
invalid_inputs = [
|
||||||
|
({'a': set()}, ['Value must be valid JSON.']),
|
||||||
|
]
|
||||||
|
outputs = [
|
||||||
|
({
|
||||||
|
'a': 1,
|
||||||
|
'b': ['some', 'list', True, 1.23],
|
||||||
|
'3': 3
|
||||||
|
}, {
|
||||||
|
'a': 1,
|
||||||
|
'b': ['some', 'list', True, 1.23],
|
||||||
|
'3': 3
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
field = serializers.JSONField()
|
||||||
|
|
||||||
|
|
||||||
|
class TestBinaryJSONField(FieldValues):
|
||||||
|
"""
|
||||||
|
Values for `JSONField` with binary=True.
|
||||||
|
"""
|
||||||
|
valid_inputs = [
|
||||||
|
('{"a": 1, "3": null, "b": ["some", "list", true, 1.23]}', {
|
||||||
|
'a': 1,
|
||||||
|
'b': ['some', 'list', True, 1.23],
|
||||||
|
'3': None
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
invalid_inputs = [
|
||||||
|
('{"a": "unterminated string}', ['Value must be valid JSON.']),
|
||||||
|
]
|
||||||
|
outputs = [
|
||||||
|
({
|
||||||
|
'a': 1,
|
||||||
|
'b': ['some', 'list', True, 1.23],
|
||||||
|
'3': None
|
||||||
|
}, '{"a": 1, "3": null, "b": ["some", "list", true, 1.23]}'),
|
||||||
|
]
|
||||||
|
field = serializers.JSONField(binary=True)
|
||||||
|
|
||||||
|
|
||||||
# Tests for FieldField.
|
# Tests for FieldField.
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user