Skip to content

Commit 26e51ec

Browse files
authored
When HTML form input is used with JSONField, treat the input as a JSON encoded string, not a JSON primative. (encode#4565)
1 parent b419970 commit 26e51ec

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

rest_framework/fields.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1594,9 +1594,21 @@ def __init__(self, *args, **kwargs):
15941594
self.binary = kwargs.pop('binary', False)
15951595
super(JSONField, self).__init__(*args, **kwargs)
15961596

1597+
def get_value(self, dictionary):
1598+
if html.is_html_input(dictionary) and self.field_name in dictionary:
1599+
# When HTML form input is used, mark up the input
1600+
# as being a JSON string, rather than a JSON primative.
1601+
class JSONString(six.text_type):
1602+
def __new__(self, value):
1603+
ret = six.text_type.__new__(self, value)
1604+
ret.is_json_string = True
1605+
return ret
1606+
return JSONString(dictionary[self.field_name])
1607+
return dictionary.get(self.field_name, empty)
1608+
15971609
def to_internal_value(self, data):
15981610
try:
1599-
if self.binary:
1611+
if self.binary or getattr(data, 'is_json_string', False):
16001612
if isinstance(data, six.binary_type):
16011613
data = data.decode('utf-8')
16021614
return json.loads(data)

tests/test_fields.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,19 @@ class TestJSONField(FieldValues):
17561756
]
17571757
field = serializers.JSONField()
17581758

1759+
def test_html_input_as_json_string(self):
1760+
"""
1761+
HTML inputs should be treated as a serialized JSON string.
1762+
"""
1763+
class TestSerializer(serializers.Serializer):
1764+
config = serializers.JSONField()
1765+
1766+
data = QueryDict(mutable=True)
1767+
data.update({'config': '{"a":1}'})
1768+
serializer = TestSerializer(data=data)
1769+
assert serializer.is_valid()
1770+
assert serializer.validated_data == {'config': {"a": 1}}
1771+
17591772

17601773
class TestBinaryJSONField(FieldValues):
17611774
"""

0 commit comments

Comments
 (0)