Fix JSONField.

This commit is contained in:
Viktor Danyliuk 2018-07-24 19:06:23 +03:00
parent f404fda29c
commit 42049daf75
2 changed files with 23 additions and 25 deletions

View File

@ -1756,6 +1756,12 @@ class HStoreField(DictField):
class JSONField(Field):
class JSONString(six.text_type):
def __new__(self, value):
ret = six.text_type.__new__(self, value)
ret.is_json_string = True
return ret
default_error_messages = {
'invalid': _('Value must be valid JSON.')
}
@ -1765,20 +1771,21 @@ class JSONField(Field):
super(JSONField, self).__init__(*args, **kwargs)
def get_value(self, dictionary):
if html.is_html_input(dictionary) and self.field_name in dictionary:
# When HTML form input is used, mark up the input
# as being a JSON string, rather than a JSON primitive.
class JSONString(six.text_type):
def __new__(self, value):
ret = six.text_type.__new__(self, value)
ret.is_json_string = True
return ret
return JSONString(dictionary[self.field_name])
return dictionary.get(self.field_name, empty)
value = dictionary.get(self.field_name, empty)
if isinstance(value, six.binary_type):
value = value.decode('utf-8')
if isinstance(value, six.text_type):
return self.JSONString(value)
return value
def to_internal_value(self, data):
try:
if self.binary or getattr(data, 'is_json_string', False):
serialized_json_types = (
six.text_type,
six.binary_type,
self.JSONString
)
if self.binary or isinstance(data, serialized_json_types):
if isinstance(data, six.binary_type):
data = data.decode('utf-8')
return json.loads(data)

View File

@ -2080,11 +2080,15 @@ class TestJSONField(FieldValues):
'a': 1,
'b': ['some', 'list', True, 1.23],
'3': None
}),
}), (
'{"a":1}',
{'a': 1}
)
]
invalid_inputs = [
({'a': set()}, ['Value must be valid JSON.']),
({'a': float('inf')}, ['Value must be valid JSON.']),
('invalid json', ['Value must be valid JSON.']),
]
outputs = [
({
@ -2099,19 +2103,6 @@ class TestJSONField(FieldValues):
]
field = serializers.JSONField()
def test_html_input_as_json_string(self):
"""
HTML inputs should be treated as a serialized JSON string.
"""
class TestSerializer(serializers.Serializer):
config = serializers.JSONField()
data = QueryDict(mutable=True)
data.update({'config': '{"a":1}'})
serializer = TestSerializer(data=data)
assert serializer.is_valid()
assert serializer.validated_data == {'config': {"a": 1}}
class TestBinaryJSONField(FieldValues):
"""