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
Required Optional fields #990
Comments
Humm, the answer is "not really". Currently the best solution might be allowing The reason for this is that although I guess in theory we could add a |
It seems a little unconventional/non-pythonic to me that That said, in practice having Moreover, the schema currently generated by Optional is what I want in most cases, so if it is extra work to support both (and I suspect it would be), I’m glad it works the way it does now. But I would be in favor of adding a |
How about we do Cue: someone comes along and abuses us with "Optional fields aren't optional! Rant Rant Rant". However, it is annoying not to have nullable fields which are required. Other options:
|
I think I’d prefer switching the behavior in v2 over adding a config setting. I’d also be okay leaving it as is; I’ll think about it. I just think config settings come with a lot of maintenance burden. I’m not super worried about people saying Optional isn’t Optional, since, while yes that is maybe weird, for better or worse it’s also the convention everywhere else. It won’t surprise me if someone complains, but I think “convention” offers an easy response. Nullable as a name sounds better to me than RequiredOptional 👍. |
I think using from typing import Optional
from pydantic import BaseModel, Field
class Metadata(BaseModel):
nullable_field: Optional[str] = Field(...) That would mean that the nullable_field can take That's what I think I would imagine. (That independent of how we end up handling #1028). |
Agreed, let's go with Then change the behaviour in v2 so that all fields without a default value are required regardless of whether they're optional. |
About having I can imagine how it could feel weird to have something without an explicit But at the same time, I could imagine feeling weird about having something declared as So, I guess it's kind of a fuzzy area... we'll get the rant anyway 😂 Given that, I guess I would prefer to follow the convention in About nullables / required-optional, we'll be able to achieve that with That still leaves open the discussion for how We'll still be able to achieve both functionalities with |
This comment has been minimized.
This comment has been minimized.
I’m the kind of guy who is known to rant about optionals, nulls, zeros, empty strings, empty arrays and empty objects and how all of them are distinct cases. Would really like if all of the cases here and in various linked issues could be easily expressed in a Pydantic model and mapped to JSON Schema equivalents. I’ll try to summarize the current ways and workarounds to do it:
Is that right, are those the easiest workarounds, and does the above cover all interesting cases? (Cue OpenAPI users bickering that arrays in |
@yurikhan How would you implement "a field that may be omitted, but may not be null if the field is supplied"? class Foo(BaseModel):
foo: int = Field(default=None)
Foo() # OK: Don't expect to see a ValidationError because only supplied fields are validated
Foo(foo=None) # Not OK: Expect to see a ValidationError because `foo` is not an `int`, but no error raised |
Hello @lsorber class Foo(BaseModel):
foo: int = Field(default=None)
@validator('foo')
def set_value_not_none(cls, v):
assert v is not None
return v But the field is still set in the model. If we actually want the field not to be set at all it requires more work and probably use a custom |
Thanks for the quick response @PrettyWood! I was heading the same direction with a validator-based workaround, but just submitted an issue (#1761) with a different validator-less workaround if you're interested. |
@lsorber As far as I understand, in the current version a validator is the way to go. It is a minor annoyance that the field behaves as if set explicitly, but, because it cannot validly be None, testing for In some places in my team’s code that doesn’t use Pydantic (yet?), we use a different sentinel value to represent missing keys. |
Ended up changing how the extract settings worked a bit. Now there's a custom validator to ensure that the value doesn't come in as `null`. This mostly forces the API to act more like just passing human-ish values to the config.yaml. I ran into some fun issues due to pydantic/pydantic#990, so went with it defaulting to a custom class that I end up manually removing from the model before dumping back out as JSON or YAML. Also, now I have a lot of the fields expressed in code. Going to try creating dynamic forms (and maybe build the settings in the docs later). Still a lot of work to do in the frontend. This PR was supposed to be for that, but a lot more backend issues kept cropping up!
How about changing the issue name to required nullable fields |
In v2 we have made optional fields required if you don't explicitly set a default value. You just need to set the default to |
For anyone like me who was looking for information on how to output these models, you can use For example: class Foo(BaseModel):
foo: Optional[int] = None
Foo(foo=1).model_dump(exclude_unset=True) == {'foo': 1}
Foo().model_dump(exclude_unset=True) == {}
Foo(foo=None).model_dump(exclude_unset=True) == {'foo': None} It took me awhile to find this in the Docs, it might be worth mentioning it more prominently. Thanks! |
Question
Currently, adding an
Optional
field just removes the field from the generatedrequired
fields list in the schema/JSON schema. Is there a mechanism for having it instead generate ananyOf
field requirement and requiring a field with a null value?Please complete:
import sys; print(sys.version)
: 3.7.4 (default, Oct 12 2019, 18:55:28)import pydantic; print(pydantic.VERSION)
: 1.1I couldn't find info on this in the help manual, though the general documentation for
Union
(link) doesn't specifically call out that it behaves differently withNone
.Would love a way to generate
{"anyOf": [{"type": "string"}, {"type": null}]}
, though I realize that passing{}
and{"nullable_field": None}
will generate equivalent Pydantic models.Thanks for the help and the library!
The text was updated successfully, but these errors were encountered: