-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discriminators and internally tagged enums #498
Comments
For folks in this same situation we are working on a fix on the python (pydantic) side of the generation story for discriminated unions that makes this (a) less error prone in python (b) "just work" with typify and (c) completely roundtrippable json with no build.rs hacks. I'll post more in this issue for posterity then maybe even blog about it since it sparks joy to see two languages getting along so nicely. |
Finally found the vital piece of the puzzle, which was, how is "title": "InternallyTaggedEnum",
"oneOf": [
{
"type": "object",
"required": [
"tag"
],
"properties": {
"tag": {
"type": "string",
"enum": [
"Alpha"
]
}
}
}, This elucidated things quite a bit, this matches the comment, but I didn't quite believe the comment when I read it. For instance I could see internal tags being in the jsonschema (with the openapi extension) or with draft jsonschema 6 like: "tag": {
"type": "string",
"const": "Alpha"
} but in the case I'm fighting we are doing python trickery to make the |
First--as you've observed--we don't support
That said, I do hope to support You raise another point: we look for singleton enumerated values, but not
I see. For what it's worth, I believe that if It this the type you ideally want to see? #[serde(tag = "my_type")]
pub enum FbzItem {
FooBar(FooBar),
Baz(Baz),
} I'm not sure what it means for serde if there's a conflict between the tag property and the struct... but I guess in this case it would probably work out. |
Yes, the real question is how to get that #[serde(tag = "my_type")]
pub enum FbzItem {
FooBar(FooBar),
Baz(Baz),
} I'm trying your PR now, still working on tweaking the jsonschema to make it go. |
I just realized there's one impedance mismatch between what I'm doing and what the new typify code is doing. I want a union type so I can do {
"$defs": {
"EventA": {
"properties": { "event_type": { "const": "EventA" } },
"required": [ "event_type" ],
"title": "EventA",
"type": "object"
},
"EventB": {
"properties": { "event_type": { "const": "EventB" } },
"required": [ "event_type" ],
"title": "EventB",
"type": "object"
}
},
"properties": {
"events": {
"items": {
"anyOf": [
{ "$ref": "#/$defs/EventA" },
{ "$ref": "#/$defs/EventB" }
]
},
"title": "Events",
"type": "array"
}
},
"required": [
"events"
],
"title": "EventsContainer",
"type": "object"
} so here I'm defining the container and then the items in it. the I may be barking up the wrong tree and the same code path is being hit, I will explore more deeply, likely adding something like this to a unit test. |
I'm not sure if this is fully related, but along these lines, I'm also having trouble making the tag work because the enum arm names don't match. They're not matching the mapping names, nor are they matching the That is, something like this: "features": {
"type": "array",
"items": {
"discriminator": {
"propertyName": "type",
"mapping": {
"X": "#/definitions/FeatureTypeX",
"Y": "#/definitions/FeatureTypeY"
}
},
"oneOf": [
{
"title": "X",
"$ref": "#/definitions/FeatureTypeX"
},
{
"title": "Y",
"$ref": "#/definitions/FeatureTypeY"
},
]
}
}, Produces: #[serde(untagged)]
pub enum FieldFeaturesItem{
TypeX(FeatureTypeX),
TypeY(FeatureTypeY)
} instead of say: #[serde(untagged)]
pub enum FieldFeaturesItem{
X(FeatureTypeX),
Y(FeatureTypeY)
} |
In this situation, |
@colmanhumphrey I'm seeing this from main: #[serde(untagged)]
pub enum FeatureItem {
X(FeatureTypeX),
Y(FeatureTypeY),
} I recall some fixes in this domain, but... not specifically what might have led to the behavior change. In any case: mission accomplished? |
Oh great! |
Hello! Thanks so much for typify.
I have a relatively simple issue to explain, with some code samples. I have some discriminated unions which simply need
#[serde(tag = "my_type")]
instead of#[serde(untagged)]
but they keep coming up untagged. This leads to one item getting parsed as the other and vice versa, which isn't what I want. I can edit the generated code, but I'd really love to get typify to honor thediscriminator.propertyName
that pydantic produces in its jsonschema as the preferred tag.Of course
propertyName
is some offshoot of jsonschema proper (OAI I suppose), but it solves a problem and I'd love to either support it directly or have a way to override the parameters of the serde field attribute programmatically?In short:
produces an attribute of:
#[serde(untagged)]
when in my opinion (and experience because changing this works) it should produce:
#[serde(tag="my_type")
based off of propertyName.I put the runnable example code in a repo: https://github.com/rseymour/typify-tag-example/tree/main
I think I could fix this myself, but I haven't been able to correlate the code to the strings it outputs for annotations.
[addendum]
If there's a way to fix the jsonschema itself to produce internally tagged enums that's also an option.
The text was updated successfully, but these errors were encountered: