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
parse_obj() / json() not called recursively / inconsistent parse_obj() behavior #1287
Comments
This seems somewhat related to #1193 |
I agree it would be elegant if the same method was used for initialising models publicly and recursively creating models, I think this is something we can resolve in v2, but likely not before. For now, instead you can modify |
I don't know when you think |
I understand that the JSON decoder specified in In my case, I wanted to work around some pydantic behavior. So I took the standard approach and sub-classed to adjust how a method works. That possibility was removed. The .json() method is more of a handy shortcut to an external function. When a developer overrides a method it is expected that it will be called instead of the super()'s. This doesn't appear to be happening. That is all. My situation is the following:We are trying to create a This particular model is to be used in a WireShark type of application that watches topics on a message exchange and shows their contents in webpage. We do not want the web server to couple an ever expanding set of pydantic models from our library of modules that feed into the message exchange. In most cases we just receive a message from the exchange and forward it over to websocket clients. There is no need to do a lot of validation or anything on the data. The complete payload goes something like this: class MyBaseModel(BaseModel):
__extra_field_a__ = ...
__extra_field_b__ = ....
def extra_method_a(): ...
def extra_method_b(): ...
class Header(MyBaseModel):
timestamp: float
source: str
destination: str
class AnyData(MyBaseModel):
__root__: Dict[str, Any]
class BasePayload(MyBaseModel):
header: Header
data: MyBaseModel
class AnyDataPayload(MyBaseModel)
data: AnyData There are many "Data" payload classes. We don't want to couple them in this case. We just want to use |
This is especially important with roots of different types, such as this: class MinMaxRange(BaseModel):
__root__: Tuple[float, float]
class Config:
title = "Range (min, max)" This works for both >>> MinMaxRange(__root__=(1,2)).json()
'[1.0, 2.0]'
>>> MinMaxRange.parse_obj([1,2])
MinMaxRange(__root__=(1.0, 2.0)) But does not work when embedded in a different object for either class LootCrate(BaseModel):
levelReq: MinMaxRange >>> LootCrate(levelReq=MinMaxRange(__root__=(1,2))).json()
'{"levelReq": {"__root__": [1.0, 2.0]}}' # incorrect
>> LootCrate.parse_obj(dict(levelReq=(1,2)))
ValidationError: 1 validation error for LootCrate
levelReq
value is not a valid dict (type=type_error.dict) Aside: The motivation behind this usage is schema generation. While a Tuple could be used directly in the parent object, it would require duplication of schema metadata in every field that uses this type. |
Will there be any movement on this issue in the near future? |
Related issue: #1193. Will probably be tackled in v2 |
Closed by #2238 |
Bug
Output of
python -c "import pydantic.utils; print(pydantic.utils.version_info())"
:Notice in the code snippet that
parse_obj()
accepts just{}
for data when provided directly to the object but not when provided to an encapsulating model. This is unexpected. To further make this situation difficult, you cannot just override a method because they don't seem to be called recursively. This, to me, is also unexpected.The text was updated successfully, but these errors were encountered: