Repository: encode/django-rest-framework

Issue:
docs: JSON input to JSONField is not parsed correctly
## Checklist

- [x] I have verified that that issue exists against the `master` branch of Django REST framework.
- [x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- [x] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
- [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](http://www.django-rest-framework.org/topics/third-party-resources/#about-third-party-packages) where possible.)
- [x] I have reduced the issue to the simplest possible case.
- [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

## Steps to reproduce
1. Create a JSONField on a serializer
2. Submit `{"a": "test"}` to the field through docs
3. Breakpoint at the return of `JSONField.to_internal_value()`

## Expected behavior
The returned data is a dictionary with a single key `a` that has a value which is string `test`.

## Actual behavior
The returned data is the string `{"a": "test"}`



Discussion:
This verified on release version 3.7.7.
I have narrowed this down to the point where I am confident to conclude that the issue is that the `data-type` attribute is set to `string` on the input element of the `JSONField`. Setting `data-type` to `object` produce the desired behaviour. Now I just need to figure out how to do just that.
Hey @beruic. Thanks for the report. 

Sounds like this will be coming out of `coreschema`. I'm just in the process of pulling that into DRF for v3.8 now. (#5855) 

There issue will be here: 

https://github.com/core-api/python-coreschema/blob/494435d8fbaff12285094e99c54c38f5a1434afb/coreschema/encodings/html.py#L54-L74

I'll see if I can close this whilst I'm porting this to DRF. 
You are right that this is related to `coreschema`, but the fix lies in `rest_framework.schemas.inspectors.field_to_schema()`. I have solved this just now in DRF. Expect a pull request soon.

I cannot however fix it for `DictField`, which has the same problem with input, because `coreschema.schema.Object` does not have an `items` argument for child schema like `coreschema.schema.Array` does. I think that a `coreschema.schema.Dictionary` is needed because, while `coreschema.schema.Object` has a `properties` argument, it seems to validate per key. I was considering making a feature request for `coreschema`, but if I understand you correctly, that is not going to be necessary, but we have to fix it in DRF.
Thoughts?

Resolving patch:
diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py
--- a/rest_framework/schemas/inspectors.py
+++ b/rest_framework/schemas/inspectors.py
@@ -95,6 +95,8 @@ def field_to_schema(field):
             description=description,
             format='date-time'
         )
+    elif isinstance(field, serializers.JSONField):
+        return coreschema.Object(title=title, description=description)
 
     if field.style.get('base_template') == 'textarea.html':
         return coreschema.String(
@@ -102,6 +104,7 @@ def field_to_schema(field):
             description=description,
             format='textarea'
         )
+
     return coreschema.String(title=title, description=description)
 
 


Test patch:
diff --git a/tests/test_schemas.py b/tests/test_schemas.py
--- a/tests/test_schemas.py
+++ b/tests/test_schemas.py
@@ -17,6 +17,7 @@
     AutoSchema, ManualSchema, SchemaGenerator, get_schema_view
 )
 from rest_framework.schemas.generators import EndpointEnumerator
+from rest_framework.schemas.inspectors import field_to_schema
 from rest_framework.schemas.utils import is_list_view
 from rest_framework.test import APIClient, APIRequestFactory
 from rest_framework.utils import formatting
@@ -763,6 +764,46 @@ class CustomView(APIView):
         link = view.schema.get_link(path, method, base_url)
         assert link == expected
 
+    def test_field_to_schema(self):
+        label = 'Test label'
+        help_text = 'This is a helpful test text'
+
+        cases = [
+            # tuples are ([field], [expected schema])
+            # TODO: Add remaining cases
+            (
+                serializers.BooleanField(label=label, help_text=help_text),
+                coreschema.Boolean(title=label, description=help_text)
+            ),
+            (
+                serializers.DecimalField(1000, 1000, label=label, help_text=help_text),
+                coreschema.Number(title=label, description=help_text)
+            ),
+            (
+                serializers.FloatField(label=label, help_text=help_text),
+                coreschema.Number(title=label, description=help_text)
+            ),
+            (
+                serializers.IntegerField(label=label, help_text=help_text),
+                coreschema.Integer(title=label, description=help_text)
+            ),
+            (
+                serializers.DateField(label=label, help_text=help_text),
+                coreschema.String(title=label, description=help_text, format='date')
+            ),
+            (
+                serializers.DateTimeField(label=label, help_text=help_text),
+                coreschema.String(title=label, description=help_text, format='date-time')
+            ),
+            (
+                serializers.JSONField(label=label, help_text=help_text),
+                coreschema.Object(title=label, description=help_text)
+            ),
+        ]
+
+        for case in cases:
+            self.assertEqual(field_to_schema(case[0]), case[1])
+
 
 def test_docstring_is_not_stripped_by_get_description():
     class ExampleDocstringAPIView(APIView):