When HTML form input is used with JSONField, treat the input as a JSON encoded string, not a JSON primative. (#4565)

This commit is contained in:
Tom Christie 2016-10-12 14:04:10 +01:00 committed by GitHub
parent b419970431
commit 26e51ecd6c
2 changed files with 26 additions and 1 deletions

View File

@ -1594,9 +1594,21 @@ class JSONField(Field):
self.binary = kwargs.pop('binary', False) self.binary = kwargs.pop('binary', False)
super(JSONField, self).__init__(*args, **kwargs) 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 primative.
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)
def to_internal_value(self, data): def to_internal_value(self, data):
try: try:
if self.binary: if self.binary or getattr(data, 'is_json_string', False):
if isinstance(data, six.binary_type): if isinstance(data, six.binary_type):
data = data.decode('utf-8') data = data.decode('utf-8')
return json.loads(data) return json.loads(data)

View File

@ -1756,6 +1756,19 @@ class TestJSONField(FieldValues):
] ]
field = serializers.JSONField() 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): class TestBinaryJSONField(FieldValues):
""" """