I have a returned result from a webservice, whose values come as they are (see example). The keys are not Optional and must be included.
2 validation errors for Result:
- cause –
str type expected (type=type.error.str) - urls –
str type expected (type=type.error.str)
{ 'code': 0, 'codetext': 'blablabla', 'status': None, 'cause': None, 'urls': None }
class Result(BaseModel):
code: int
codetext: str
status: str = ""
cause: str = ""
urls: str = ""
@validator("status", "cause", "urls")
def replace_none(cls, v):
return v or "None"
First questions is, what is the correct way to handle the None values coming as answer from the webservice and set to ‘None’ (with single-quotation marks and None as String) and secondly, why are there only 2 and not 3 errors?
Advertisement
Answer
You can mark fields as required but optional by declaring the field optional and using ellipsis (...) as its value. Here is a complete, simplified example with tests to verify it works (execute with pytest <file>):
import pytest
from pydantic import BaseModel, ValidationError, validator
class Result(BaseModel):
code: int
status: str | None = ...
@validator("status")
def replace_none(cls, v):
return v or "None"
def test_result():
p = Result.parse_obj({"code": 1, "status": "test status"})
assert p.code == 1
assert p.status == "test status"
def test_required_optionals():
"""Test that missing fields raise an error."""
with pytest.raises(ValidationError):
Result.parse_obj({"code": 1})
def test_required_optional_accepts_none():
"""Test that none values are accepted."""
p = Result.parse_obj(
{
"code": 0,
"status": None,
}
)
assert p.status == "None"