Closed seveneves closed 3 days ago
Please take a look at related issue I raised some time ago: https://github.com/softwaremill/tapir/issues/3765 https://github.com/swagger-api/swagger.io/issues/348
It seems there's a couple of variants, in which we can render discriminators & mappings. From what I understand these are:
oneOf
+ discriminator, plain typesanyOf
instead of oneOf
, const
schema attributes for the discriminator fieldsIt would be great to be able to use just a single representation, or at least constraint the possibilities to a set of "best ones". Though - which would those "best ones" be?
(btw. - I think discriminators are useful if only for the fact that code generators might use them to create deserialization code efficiently)
Const is just more explicit representation of what single-value enum does.
See https://github.com/swagger-api/swagger.io/issues/348#issuecomment-2111886039
I actually believe having discriminator
property named at the generic level, and having const
constraint at leafs is enough to derive all the representations.
Maybe reasoning like that:
oneOf
; its either Cat
or Dog
or Rat
, not mix of above, not "pick first to match"oneOf
In the end - for me - best final representation should match model described above - just oneOf+const, and named and required discriminator field. I have no idea why the whole discriminator mapping idea was added to openapi - if one can have exactly same functionality and performance with just one additional attribute attached to discriminator field definition. See how nicely this all scales:
discriminator
First is enough to parse/validate correctly. Second is more strict about structure. Third allows to build mapping tables and optimize.
In our use case, we use tapir for the backend and generate TypeScript clients based on the OpenApi Specification generated out of Tapir schema. So having "one-to-one" strictness of type definitions in Scala with what TypeScript is allowed to do would be the "best one" solution to me.
And I think this can be only achieved with either enum validation or constant discriminator field.
ok, thank you very much for the detailed explanations. Let's go with the const validator, as I think it's the most precise. Now we just need an implementation :)
Now we just need an implementation :)
@adamw looking briefly into the support of const
in tapir Schema, it is not supported at all.
Could you please leave some pointers of how to add support for const
. And what to be aware of when adding a new feature like const
support? I assume new implementation of SchemaType
will be required that just wraps a primitive value with a type definition.
Please see here #3765
We implemented this with additional Schema.const: Option[(T, Option[Any])]
property, but did not manage to get binary compatibilty, so dropped this idea for some pre/postprocessing trickery that allowed us to get desired effect in production without changing tapir.
It would be nice to simply have Schema.const
attribute supported.
@seveneves @adamw I reopened our take on const
: https://github.com/softwaremill/tapir/pull/3763.
Tapir version: 1.10.12
Scala version: 3.3.3
Given following model
It will have the following OpenApi specification generated
Schemas for
Cat
andRat
are essentially the same and only can be distinguished by discriminator valuepet
. However, it seems that OpenAPI specification does not require discriminator to actually be enforced when validatingoneOf
type ofSchema
definition.This is answered in the discussion of OpenAPI specification https://github.com/OAI/OpenAPI-Specification/discussions/3608 where the suggestion is to use
anyOf
instead ofoneOf
to make validation work (a library I use does fail the validation ofoneOf
becauseRat
andCat
are the similar schemas structurally).One easy fix for a such problem is to add a validator of type
enum
to each discriminator fieldpet
. So then the definition would become as follows. Such validation will make sure that typeCat
andRat
are not subsets of each other.I would like to make a suggestion to extend
sttp.tapir.generic.Configuration
by introducing a new flag asvalidateDiscriminatorValue: Boolean = false
and then add enum validator in methodsttp.tapir.SchemaType.SCoproduct#addDiscriminatorField
.I can submit a change request if this is accepted