From ab6444a32e222a4b9df12620fc484814c165f701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Noss?= Date: Fri, 19 Jul 2019 13:13:26 +0200 Subject: [PATCH] inspectors: add support for JSONField (#417) --- docs/settings.rst | 1 + src/drf_yasg/app_settings.py | 1 + src/drf_yasg/inspectors/__init__.py | 6 +++--- src/drf_yasg/inspectors/field.py | 14 +++++++++++++- tests/test_schema_generator.py | 20 ++++++++++++++++++++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 7a10b5f..a2e4bdb 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -85,6 +85,7 @@ to this list. :class:`'drf_yasg.inspectors.ChoiceFieldInspector' <.inspectors.ChoiceFieldInspector>`, |br| \ :class:`'drf_yasg.inspectors.FileFieldInspector' <.inspectors.FileFieldInspector>`, |br| \ :class:`'drf_yasg.inspectors.DictFieldInspector' <.inspectors.DictFieldInspector>`, |br| \ +:class:`'drf_yasg.inspectors.JSONFieldInspector' <.inspectors.JSONFieldInspector>`, |br| \ :class:`'drf_yasg.inspectors.HiddenFieldInspector' <.inspectors.HiddenFieldInspector>`, |br| \ :class:`'drf_yasg.inspectors.RecursiveFieldInspector' <.inspectors.RecursiveFieldInspector>`, |br| \ :class:`'drf_yasg.inspectors.SerializerMethodFieldInspector' <.inspectors.SerializerMethodFieldInspector>`, |br| \ diff --git a/src/drf_yasg/app_settings.py b/src/drf_yasg/app_settings.py index 6f6e536..6592d34 100644 --- a/src/drf_yasg/app_settings.py +++ b/src/drf_yasg/app_settings.py @@ -12,6 +12,7 @@ SWAGGER_DEFAULTS = { 'drf_yasg.inspectors.ChoiceFieldInspector', 'drf_yasg.inspectors.FileFieldInspector', 'drf_yasg.inspectors.DictFieldInspector', + 'drf_yasg.inspectors.JSONFieldInspector', 'drf_yasg.inspectors.HiddenFieldInspector', 'drf_yasg.inspectors.RelatedFieldInspector', 'drf_yasg.inspectors.SerializerMethodFieldInspector', diff --git a/src/drf_yasg/inspectors/__init__.py b/src/drf_yasg/inspectors/__init__.py index cb979c8..654de79 100644 --- a/src/drf_yasg/inspectors/__init__.py +++ b/src/drf_yasg/inspectors/__init__.py @@ -4,8 +4,8 @@ from .base import ( ) from .field import ( CamelCaseJSONFilter, ChoiceFieldInspector, DictFieldInspector, FileFieldInspector, HiddenFieldInspector, - InlineSerializerInspector, RecursiveFieldInspector, ReferencingSerializerInspector, RelatedFieldInspector, - SerializerMethodFieldInspector, SimpleFieldInspector, StringDefaultFieldInspector + InlineSerializerInspector, JSONFieldInspector, RecursiveFieldInspector, ReferencingSerializerInspector, + RelatedFieldInspector, SerializerMethodFieldInspector, SimpleFieldInspector, StringDefaultFieldInspector ) from .query import CoreAPICompatInspector, DjangoRestResponsePagination from .view import SwaggerAutoSchema @@ -24,7 +24,7 @@ __all__ = [ # field inspectors 'InlineSerializerInspector', 'RecursiveFieldInspector', 'ReferencingSerializerInspector', 'RelatedFieldInspector', - 'SimpleFieldInspector', 'FileFieldInspector', 'ChoiceFieldInspector', 'DictFieldInspector', + 'SimpleFieldInspector', 'FileFieldInspector', 'ChoiceFieldInspector', 'DictFieldInspector', 'JSONFieldInspector', 'StringDefaultFieldInspector', 'CamelCaseJSONFilter', 'HiddenFieldInspector', 'SerializerMethodFieldInspector', # view inspectors diff --git a/src/drf_yasg/inspectors/field.py b/src/drf_yasg/inspectors/field.py index c852e4e..c18de72 100644 --- a/src/drf_yasg/inspectors/field.py +++ b/src/drf_yasg/inspectors/field.py @@ -745,11 +745,23 @@ class HiddenFieldInspector(FieldInspector): return NotHandled +class JSONFieldInspector(FieldInspector): + """Provides conversion for ``JSONField``.""" + + def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): + SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs) + + if isinstance(field, serializers.JSONField) and swagger_object_type == openapi.Schema: + return SwaggerType(type=openapi.TYPE_OBJECT) + + return NotHandled + + class StringDefaultFieldInspector(FieldInspector): """For otherwise unhandled fields, return them as plain :data:`.TYPE_STRING` objects.""" def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): # pragma: no cover - # TODO unhandled fields: TimeField JSONField + # TODO unhandled fields: TimeField SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs) return SwaggerType(type=openapi.TYPE_STRING) diff --git a/tests/test_schema_generator.py b/tests/test_schema_generator.py index 0c305a6..2400238 100644 --- a/tests/test_schema_generator.py +++ b/tests/test_schema_generator.py @@ -273,3 +273,23 @@ def test_nested_choice_in_array_field(choices, field, expected_type): swagger = generator.get_schema(None, True) property_schema = swagger['definitions']['Array']['properties']['array']['items'] assert property_schema == openapi.Schema(title='Array', type=expected_type, enum=choices) + + +def test_json_field(): + class TestJSONFieldSerializer(serializers.Serializer): + json = serializers.JSONField() + + class JSONViewSet(viewsets.ModelViewSet): + serializer_class = TestJSONFieldSerializer + + router = routers.DefaultRouter() + router.register(r'jsons', JSONViewSet, **_basename_or_base_name('jsons')) + + generator = OpenAPISchemaGenerator( + info=openapi.Info(title='Test json field generator', default_version='v1'), + patterns=router.urls + ) + + swagger = generator.get_schema(None, True) + property_schema = swagger["definitions"]["TestJSONField"]["properties"]["json"] + assert property_schema == openapi.Schema(title='Json', type=openapi.TYPE_OBJECT)