Pydantic: Limit error response in large union

Created on 2 Oct 2019  路  3Comments  路  Source: samuelcolvin/pydantic

Question

I am looking for ways to only see an error in a specific element of a union.

We have some models similar to this example from the docs:

...

class Dessert(BaseModel):
    kind: str

class Pie(Dessert):
    kind: Literal['pie']
    flavor: Optional[str]

class ApplePie(Pie):
    flavor: Literal['apple']

class PumpkinPie(Pie):
    flavor: Literal['pumpkin']

class Meal(BaseModel):
    dessert: Union[ApplePie, PumpkinPie, Pie, Dessert]

...

For the Union in the Meal class, if the input satisfies none of the models, it would throw errors for all. Our use case has over 10 different models that have different fields in the Union and the response is difficult to parse. Each different type is based on a literal string similar to above.
Is there a way to limit/filter errors so that the response is more actionable?

Previously to avoid this, I had one large generic model with Optional field on all elements that were only in some cases. And then custom validators for each element to see whether it was required for this type.

Please complete:

  • OS: macOS, Linux
  • Python version import sys; print(sys.version): 3.7
  • Pydantic version import pydantic; print(pydantic.VERSION): 0.32.2
question

Most helpful comment

Currently, I don't think there is a clean way to validate a union-typed field without seeing all the errors.


I recently put a little effort into building a type called DiscriminatedUnion with the same API as Union (and which is seen exactly the same as a Union by mypy), but which pydantic treats specially:

  • During ~field~ type initialization, it would check that:

    • All models in the (discriminated) union have the same value of a config setting indicating the discriminator property

    • All models in the union have that field annotated as a distinct Literal string

  • During parsing, it would:

    • First, look for the discriminator value; if invalid, that would be the only error you'd see

    • If the discriminator is valid, try to parse the payload as the appropriate discriminated model. If parsing fails, you'd only see the one error; otherwise the parsed output would be an object of the discriminated type

I haven't finished the implementation, but I'm convinced it should be possible to implement without too much effort. It should also play nice with the discriminator concept in OpenAPI (though I think most tools have weak support for that, at best).

I'd be curious if there are others interested in this version of the implementation, or if a different API would be preferable.

All 3 comments

Currently, I don't think there is a clean way to validate a union-typed field without seeing all the errors.


I recently put a little effort into building a type called DiscriminatedUnion with the same API as Union (and which is seen exactly the same as a Union by mypy), but which pydantic treats specially:

  • During ~field~ type initialization, it would check that:

    • All models in the (discriminated) union have the same value of a config setting indicating the discriminator property

    • All models in the union have that field annotated as a distinct Literal string

  • During parsing, it would:

    • First, look for the discriminator value; if invalid, that would be the only error you'd see

    • If the discriminator is valid, try to parse the payload as the appropriate discriminated model. If parsing fails, you'd only see the one error; otherwise the parsed output would be an object of the discriminated type

I haven't finished the implementation, but I'm convinced it should be possible to implement without too much effort. It should also play nice with the discriminator concept in OpenAPI (though I think most tools have weak support for that, at best).

I'd be curious if there are others interested in this version of the implementation, or if a different API would be preferable.

From the perspective of the current codebase I鈥檓 working with that implementation would be highly desirable.

I agree that it the swagger may behave weirdly but it already has some issues with anyOf as we discussed on another issue :)

I entirely agree that this would be great, see my comment: https://github.com/samuelcolvin/pydantic/issues/619#issuecomment-520221891 and more below that

You can see the bodge I'm using right now for this here.

The reason I haven't worked on descriminator yet was an effort to get version 1 released. Since this should be backwards compatible it should be possible to release in v1.1.

Closing this, if there's more feedback please comment on #619.

Was this page helpful?
0 / 5 - 0 ratings