如何在 pydantic 中听写或数据检查密钥
How to dict or data check keys in pydantic
class mail(BaseModel):
mailid: int
email: str
class User(BaseModel):
id: int
name: str
mails: List[mail]
data1 = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aeajhs@gmail.com'},
{'mailid':2,'email':'aeajhsds@gmail.com'}
]
}
userobj = User(**data1) # Accepted
data2 = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aeajhs@gmail.com'},
{'email':'aeajhsds@gmail.com'}
]
}
userobj = User(**data2) # Discarded or not accepted
我想检查我们传递给 pydantic 模型的字典中的键,所以如果键不存在于给定的字典中,我想丢弃该数据。
例如邮件中的data2 {'email':'aeajhsds@gmail.com'}
data2必须丢弃
您所说的“丢弃”数据并不完全清楚。
您当前的实施应该引发 ValidationError
因为 data2
中的 mails
中的第二项缺少 mailid
:
Traceback (most recent call last):
...
pydantic.error_wrappers.ValidationError: 1 validation error for User
mails -> 1 -> mailid
field required (type=value_error.missing)
如果您的意图是简单地忽略 data2
(或一般的无效输入),我建议将所有内容包装在try
-except
块,例如:
from pydantic import ValidationError
# your code here
try:
userobj = User(**data2)
except ValidationError as exc:
# Optional printout or logging:
print(f"Encountered the following error when parsing `{data2}`:\n{exc}.\nSkipping...")
程序现在将显示以下消息:
Encountered the following error when parsing `{'id': 123, 'name': 'Jane Doe', 'mails': [{'mailid': 1, 'email': 'aeajhs@gmail.com'}, {'email': 'aeajhsds@gmail.com'}]}`:
1 validation error for User
mails -> 1 -> mailid
field required (type=value_error.missing).
Skipping...
备选方案
另一方面,如果您想忽略缺少 mailid
的事实,您可以在模型定义中将其设为 Optional
,例如:
from typing import Optional
class mail(BaseModel):
mailid: Optional[int]
email: str
# ... everything stays the same
# This works now:
userobj = User(**data2)
print(userobj)
# id=123 name='Jane Doe' mails=[mail(mailid=1, email='aeajhs@gmail.com'), mail(mailid=None, email='aeajhsds@gmail.com')]
您可以像@juanpa-arrivillaga 所说的那样使用pydantic.validator
。
还有几个小技巧:
Optional
验证结束时可能为空。
pre=True
是否应该在标准验证器之前调用此验证器(否则在)
from pydantic import BaseModel, validator
from typing import List, Optional
class Mail(BaseModel):
mailid: int
email: str
class User(BaseModel):
id: int
name: str
mails: Optional[List[Mail]]
@validator('mails', pre=True)
def mail_check(cls, v):
mail_att = [i for i in Mail.__fields__.keys()]
mail_att_count = 0
for i, x in enumerate(v):
for k in dict(x).keys():
if k in mail_att:
mail_att_count += 1
if mail_att_count != len(mail_att):
v.pop(i)
mail_att_count = 0
return v
data = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aaa@gmail.com'},
{'mailid':2,'email':'bbb@gmail.com'},
{'email':'ccc@gmail.com'}
]
}
x = User(**data) # Discarded or not accepted
print(x.id)
print(x.name)
print(x.mails)
# Output
# >>123
# >>Jane Doe
# >>[Mail(mailid=1, email='aaa@gmail.com'), Mail(mailid=2, email='bbb@gmail.com')]
您可以在预验证中遍历 mails
列表并执行一个简单的 try
子句来检查每个 mail
项目是否正确:
from pydantic import BaseModel, validator
from pydantic.error_wrappers import ValidationError
from typing import List
class mail(BaseModel):
mailid: int
email: str
class User(BaseModel):
id: int
name: str
mails: List[mail]
@validator("mails", pre=True)
def must_be_valid_mail(cls, v):
ret = []
for item in list(v):
try:
mail(**item)
ret.append(item)
except ValidationError as er:
print(er)
return ret
data = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aeajhs@gmail.com'},
{'email':'aeajhsds@gmail.com'}
]
}
userobj = User(**data)
print(userobj)
class mail(BaseModel):
mailid: int
email: str
class User(BaseModel):
id: int
name: str
mails: List[mail]
data1 = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aeajhs@gmail.com'},
{'mailid':2,'email':'aeajhsds@gmail.com'}
]
}
userobj = User(**data1) # Accepted
data2 = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aeajhs@gmail.com'},
{'email':'aeajhsds@gmail.com'}
]
}
userobj = User(**data2) # Discarded or not accepted
我想检查我们传递给 pydantic 模型的字典中的键,所以如果键不存在于给定的字典中,我想丢弃该数据。
例如邮件中的data2 {'email':'aeajhsds@gmail.com'}
data2必须丢弃
您所说的“丢弃”数据并不完全清楚。
您当前的实施应该引发 ValidationError
因为 data2
中的 mails
中的第二项缺少 mailid
:
Traceback (most recent call last):
...
pydantic.error_wrappers.ValidationError: 1 validation error for User
mails -> 1 -> mailid
field required (type=value_error.missing)
如果您的意图是简单地忽略 data2
(或一般的无效输入),我建议将所有内容包装在try
-except
块,例如:
from pydantic import ValidationError
# your code here
try:
userobj = User(**data2)
except ValidationError as exc:
# Optional printout or logging:
print(f"Encountered the following error when parsing `{data2}`:\n{exc}.\nSkipping...")
程序现在将显示以下消息:
Encountered the following error when parsing `{'id': 123, 'name': 'Jane Doe', 'mails': [{'mailid': 1, 'email': 'aeajhs@gmail.com'}, {'email': 'aeajhsds@gmail.com'}]}`:
1 validation error for User
mails -> 1 -> mailid
field required (type=value_error.missing).
Skipping...
备选方案
另一方面,如果您想忽略缺少 mailid
的事实,您可以在模型定义中将其设为 Optional
,例如:
from typing import Optional
class mail(BaseModel):
mailid: Optional[int]
email: str
# ... everything stays the same
# This works now:
userobj = User(**data2)
print(userobj)
# id=123 name='Jane Doe' mails=[mail(mailid=1, email='aeajhs@gmail.com'), mail(mailid=None, email='aeajhsds@gmail.com')]
您可以像@juanpa-arrivillaga 所说的那样使用pydantic.validator
。
还有几个小技巧:
Optional
验证结束时可能为空。pre=True
是否应该在标准验证器之前调用此验证器(否则在)
from pydantic import BaseModel, validator
from typing import List, Optional
class Mail(BaseModel):
mailid: int
email: str
class User(BaseModel):
id: int
name: str
mails: Optional[List[Mail]]
@validator('mails', pre=True)
def mail_check(cls, v):
mail_att = [i for i in Mail.__fields__.keys()]
mail_att_count = 0
for i, x in enumerate(v):
for k in dict(x).keys():
if k in mail_att:
mail_att_count += 1
if mail_att_count != len(mail_att):
v.pop(i)
mail_att_count = 0
return v
data = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aaa@gmail.com'},
{'mailid':2,'email':'bbb@gmail.com'},
{'email':'ccc@gmail.com'}
]
}
x = User(**data) # Discarded or not accepted
print(x.id)
print(x.name)
print(x.mails)
# Output
# >>123
# >>Jane Doe
# >>[Mail(mailid=1, email='aaa@gmail.com'), Mail(mailid=2, email='bbb@gmail.com')]
您可以在预验证中遍历 mails
列表并执行一个简单的 try
子句来检查每个 mail
项目是否正确:
from pydantic import BaseModel, validator
from pydantic.error_wrappers import ValidationError
from typing import List
class mail(BaseModel):
mailid: int
email: str
class User(BaseModel):
id: int
name: str
mails: List[mail]
@validator("mails", pre=True)
def must_be_valid_mail(cls, v):
ret = []
for item in list(v):
try:
mail(**item)
ret.append(item)
except ValidationError as er:
print(er)
return ret
data = {
'id': 123,
'name': 'Jane Doe',
'mails':[
{'mailid':1,'email':'aeajhs@gmail.com'},
{'email':'aeajhsds@gmail.com'}
]
}
userobj = User(**data)
print(userobj)