diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 3278cf51c..e5777f10d 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -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) diff --git a/tests/test_fields.py b/tests/test_fields.py index aa3391a72..fa9978d9b 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -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): """