【发布时间】:2021-08-11 17:15:12
【问题描述】:
我正在使用遵循类继承模式的数据...我无法让 pydantic 针对某些用例正确反序列化它。
鉴于下面的代码,使用parse_* 方法时似乎没有调用验证器。 “fluffy”和“tiger”的类型是Animal,但是当反序列化“bob”Person时,他的宠物是正确的Dog类型。
还有其他方法可以解决这个问题吗?使用pydantic 不是必需的,但是能够反序列化嵌套的复杂类型(包括对象的List 和Dict)。
# modified from the following examples
# - https://github.com/samuelcolvin/pydantic/issues/2177#issuecomment-739578307
# - https://github.com/samuelcolvin/pydantic/issues/619#issuecomment-713508861
from pydantic import BaseModel
TIGER = """{ "type": "cat", "name": "Tiger the Cat", "color": "tabby" }"""
FLUFFY = """{ "type": "dog", "name": "Fluffy the Dog", "color": "brown", "breed": "rottweiler" }"""
ALICE = """{ "name": "Alice the Person" }"""
BOB = f"""{{ "name": "Bob the Person", "pet": {FLUFFY} }}"""
class Animal(BaseModel):
type: str
name: str
color: str = None
_subtypes_ = dict()
def __init_subclass__(cls, type=None):
cls._subtypes_[type or cls.__name__.lower()] = cls
@classmethod
def __get_validators__(cls):
yield cls._convert_to_real_type_
@classmethod
def _convert_to_real_type_(cls, data):
data_type = data.get("type")
if data_type is None:
raise ValueError("Missing 'type' in Animal")
sub = cls._subtypes_.get(data_type)
if sub is None:
raise TypeError(f"Unsupport sub-type: {data_type}")
return sub(**data)
class Cat(Animal, type="cat"):
hairless: bool = False
class Dog(Animal, type="dog"):
breed: str
class Person(BaseModel):
name: str
pet: Animal = None
tiger = Animal.parse_raw(TIGER)
print(f"tiger [{tiger.name}] => {type(tiger)} [{tiger.type}]")
fluffy = Animal.parse_raw(FLUFFY)
print(f"fluffy [{fluffy.name}] => {type(fluffy)} [{fluffy.type}]")
bob = Person.parse_raw(BOB)
pet = bob.pet
print(f"bob [{bob.name}] => {type(bob)}")
print(f"pet [{pet.name}] => {type(pet)}")
输出:
tiger [Tiger the Cat] => <class '__main__.Animal'>
fluffy [Fluffy the Dog] => <class '__main__.Animal'>
bob [Bob the Person] => <class '__main__.Person'>
pet [Fluffy the Dog] => <class '__main__.Dog'>
【问题讨论】: