s-knibbs / dataclasses-jsonschema

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

Add support for constant fields #63

Open s-knibbs opened 5 years ago

s-knibbs commented 5 years ago

In #62 basic support for 'Final' types was added. However the following form, which defines a constant vaued field is not currently supported:


@dataclass
class Rectangle(JsonSchemaMixin):
    max_width: Final = 20
    x: int
    y: int

This could generate one of the following schemas for the max_width field:

Draft 04:

{"enum": [20]}

Draft 06:

{"const": 20}
jobh commented 4 years ago

A workaround that seems to work for me (my use case is demarshalling based on string types, so YMMV). The __post_init__ code may not be necessary, or maybe you want to go the other way (convert from enum to int, although the enum inherits from int so it should not be necessary).

class Constant(dict):
    def __getitem__(self, value):
        if not value in self:
            typ = type(value)
            self[value] = Enum(f'<Constant_{typ.__name__}:{value}>', type=typ, names=[('value', value)])
        return dict.__getitem__(self, value)
Constant = Constant()

@dataclass
class Rectangle(JsonSchemaMixin):
    max_width: Constant[20] = Constant[20].value
    x: int
    y: int
    def __post_init__(self):
        self.max_width = Constant[20](self.max_width)

This generates {"type": "integer", "enum": [20], "default": 20} which looks right.