s-knibbs / dataclasses-jsonschema

JSON schema generation from dataclasses
MIT License
166 stars 38 forks source link

Dataclass: Unable to create schema for 'str | None' #187

Closed whyisdifficult closed 1 year ago

whyisdifficult commented 2 years ago

Problem

Dataclasses with Python 3.10-compatible typing cause warning when trying to create JSON schema for the class

How to reproduce

Assume the following definition

from typing import Optional
from dataclasses import dataclass
from dataclasses_jsonschema import JsonSchemaMixin
from dataclasses_jsonschema import SchemaType

@dataclass
class A(JsonSchemaMixin):
   id: str | None

@dataclass
class B(JsonSchemaMixin):
   id: Optional[str] = None

Running this

>>> A.json_schema(embeddable=True, schema_type=SchemaType.V3)

causes the following error:

/path-to-project/.venv/lib/python3.10/site-packages/dataclasses_jsonschema/__init__.py:696: UserWarning: Unable to create schema for 'str | None'
  warnings.warn(f"Unable to create schema for '{field_type_name}'")
{'A': {'type': 'object', 'required': ['id'], 'properties': {'id': {}}, 'x-module-name': '__main__', 'description': 'A(id: str | None)'}}

while if I run this

>>> B.json_schema(embeddable=True, schema_type=SchemaType.V3)

I get this w/o warning

{'B': {'type': 'object', 'properties': {'id': {'type': 'string'}}, 'x-module-name': '__main__', 'description': 'B(id: Optional[str])'}}

The issue seems to be caused by this bit of code: https://github.com/s-knibbs/dataclasses-jsonschema/blob/82ea3d892b70e6922ec4cbf604ccdf37198a9f55/dataclasses_jsonschema/__init__.py#L887

 @staticmethod
  def _get_field_type_name(field_type: Any) -> str:
        try:
            return field_type.__name__
        except AttributeError:
            # The types in the 'typing' module lack the __name__ attribute
            match = re.match(r'typing\.([A-Za-z]+)', str(field_type))
            return str(field_type) if match is None else match.group(1)

Setup

Python: v3.10 dataclasses_jsonschema: version 2.14.1 (but tried with the latest version as well.

s-knibbs commented 1 year ago

You need to add from __future__ import annotations to the top of the file for the these types to resolve correctly.