Skip to content

OpenAPI schema generation does not handle callable defaults #6858

@Lucidiot

Description

@Lucidiot

Checklist

  • I have verified that that issue exists against the master branch of Django REST framework.
  • I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
  • This is not a usage question. (Those should be directed to the discussion group instead.)
  • This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
  • 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

On any serializer used by a GenericAPIView, set the default for a field to any callable.

class OhNoSerializer(serializers.Serializer):
    something = serializers.FloatField(default=float)

class OhNoAPIView(CreateAPIView):
    serializer_class = OhNoSerializer
    ...

Expected behavior

Output of ./manage.py generateschema:

paths:
  /api/oh/no:
    post:
      operationId: CreateOhNo
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              required:
              - something
              properties:
                something:
                  type: number
                  default: 0.0

Actual behavior

With ./manage.py generateschema:

paths:
  /api/oh/no:
    post:
      operationId: CreateOhNo
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              required:
              - something
              properties:
                something:
                  type: number
                  default: !!python/name:builtins.float ''

With ./manage.py generateschema --format openapi-json:

Traceback (most recent call last):
  File "./manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/home/lucidiot/.virtualenvs/drf/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/home/lucidiot/.virtualenvs/drf/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/lucidiot/.virtualenvs/drf/lib/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/lucidiot/.virtualenvs/drf/lib/python3.6/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/home/lucidiot/dev/django-rest-framework/rest_framework/management/commands/generateschema.py", line 42, in handle
    output = renderer.render(schema, renderer_context={})
  File "/home/lucidiot/dev/django-rest-framework/rest_framework/renderers.py", line 1064, in render
    return json.dumps(data, indent=2).encode('utf-8')
  File "/home/lucidiot/dev/django-rest-framework/rest_framework/utils/json.py", line 25, in dumps
    return json.dumps(*args, **kwargs)
  File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.6/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/usr/lib/python3.6/json/encoder.py", line 430, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
    yield from chunks
  File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
    yield from chunks
  File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
    yield from chunks
  [Previous line repeated 7 more times]
  File "/usr/lib/python3.6/json/encoder.py", line 437, in _iterencode
    o = _default(o)
  File "/usr/lib/python3.6/json/encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'type' is not JSON serializable

How to handle defaults that depend on the request, like CurrentUserDefault, or user-defined defaults that can depend on anything ?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions