Discriminator support in DRAFT_7? #322
Replies: 1 comment 1 reply
-
Hopefully, maybe there is no need to make a PR. Or just a little one to update the documentation. Let me update your example: import json
from dataclasses import dataclass
from typing import Literal, Sequence, Union
from apischema import deserialize, discriminator, serialize
from apischema.json_schema import JsonSchemaVersion, deserialization_schema
from typing_extensions import Annotated
@dataclass
class Cat:
type: Literal["cat"] = "cat"
pass
@dataclass
class Dog:
type: Literal["dog"] = "dog"
Pets = Sequence[Annotated[Union[Cat, Dog], discriminator("type")]]
discriminator_schema = deserialization_schema(
Pets, all_refs=True, version=JsonSchemaVersion.DRAFT_7
)
assert deserialize(Pets, [{"type": "dog"}]) == [Dog()]
assert serialize(Pets, [Dog()]) == [{"type": "dog"}]
assert discriminator_schema == {
"type": "array",
"items": {
"oneOf": [{"$ref": "#/definitions/Cat"}, {"$ref": "#/definitions/Dog"}],
"discriminator": {
"propertyName": "type",
"mapping": {"cat": "#/definitions/Cat", "dog": "#/definitions/Dog"},
},
},
"definitions": {
"Cat": {
"type": "object",
"properties": {
"type": {"type": "string", "const": "cat", "default": "cat"}
},
"additionalProperties": False,
},
"Dog": {
"type": "object",
"properties": {
"type": {"type": "string", "const": "dog", "default": "dog"}
},
"additionalProperties": False,
},
},
"$schema": "http://json-schema.org/draft-07/schema#",
} When the discriminator field is not declared, I've judged that it should not be put in the schema, as the type could be used outside of a discriminated union, so one should not expect an undeclared field to be here. Actually, I'm not sure that it's really compatible with OpenAPI standard (to have a discriminator not present in fields). Maybe I could do something like this : {
"type": "array",
"items": {
"oneOf": [
{
"allOf": [
{"$ref": "#/definitions/Cat"},
{"properties": {"type": {"type": "string"}}},
]
},
{
"allOf": [
{"$ref": "#/definitions/Dog"},
{"properties": {"type": {"type": "string"}}},
]
},
],
"discriminator": {"propertyName": "type"},
},
"definitions": {
"Cat": {"type": "object", "additionalProperties": False},
"Dog": {"type": "object", "additionalProperties": False},
},
"$schema": "http://json-schema.org/draft-07/schema#",
} but there would be the issue of If you encounter some issues, you can still use schema overriding to patch them, but again, For now, I hope this trick about discriminator will do the job for you, I will have to update the documentation to include it. |
Beta Was this translation helpful? Give feedback.
-
We are using apischema to make a JSON schema for a YAML file, that is then deserialized into a sequence of objects to act as configuration for a program. We edit the YAML file using VSCode YAML editor that has support for Draft 7
We are currently using a Union with literal fields (with some converters to automate). The strategy boils down to this:
I tried to convert this to using discriminators:
Unfortunately this doesn't play nicely with the editor, as Draft 7 doesn't support discriminator, it is left with a union of two objects with no "type" field.
I was wondering what would be the best way to produce the schema from the union example from a nested type structure with discriminators? Is it something that could be done in
deserialization_schema
, or in some custom converters, or should I process the (nested) class structure before passing todeserialization_schema
?Happy to make a PR to apischema if that is the best place for code that does this.
Thanks,
Tom
Beta Was this translation helpful? Give feedback.
All reactions