From 26e51ecd6c0805770615e768e46ecc6716872670 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 12 Oct 2016 14:04:10 +0100 Subject: [PATCH] When HTML form input is used with JSONField, treat the input as a JSON encoded string, not a JSON primative. (#4565) --- rest_framework/fields.py | 14 +++++++++++++- tests/test_fields.py | 13 +++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 1894b064c..e48285005 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1594,9 +1594,21 @@ class JSONField(Field): self.binary = kwargs.pop('binary', False) 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): try: - if self.binary: + if self.binary or getattr(data, 'is_json_string', False): if isinstance(data, six.binary_type): data = data.decode('utf-8') return json.loads(data) diff --git a/tests/test_fields.py b/tests/test_fields.py index c271afa9e..6fea249ba 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1756,6 +1756,19 @@ 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): """