[英]How to validate 2 nested json using Pydantic model in python?
test1 = {
"abx": [
{
"name": "toyota",
"colors": "abc",
"demo": [
{
"name1": "pqr",
"surname": "abc",
"columns": [
{
"name2": "demo",
"nameid": "1"
}
]
}
]
},
{
"name": "suzuki",
"colors": "deq",
"demo": [
{
"name1": "abc",
"surname": "asd",
"columns": [
{
"name2": "demo1",
"nameid": "2"
}
]
}
]
}
]
}
I have 2 nested JSON and both responses have shuffle values.我有 2 个嵌套的 JSON 并且两个响应都有随机播放值。 I wanted to match using Pydantic models for testing in Python.
我想匹配使用 Pydantic 模型在 Python 中进行测试。
Is there any way to compare, validate both responses?有什么方法可以比较、验证两个响应吗?
A nested JSON can simply be represented by nested Pydantic models .嵌套的 JSON 可以简单地用嵌套的 Pydantic 模型表示。 Each object can be mapped to a model, and that model can have attributes that are other Pydantic models or a list of Pydantic models.
每个 object 都可以映射到 model,并且 model 可以具有其他 Pydantic 模型或 Pydantic 模型列表的属性。
You start with the innermost objects:你从最里面的对象开始:
{
"name2": "demo1",
"nameid": "2",
}
which can be represented as:可以表示为:
from pydantic import BaseModel, constr
class Column(BaseModel):
name2: str
nameid: constr(regex="[0-9]+") # See: https://pydantic-docs.helpmanual.io/usage/types/#arguments-to-constr
In [2]: raw = {"name2": "demo1", "nameid": "2"}
In [3]: col = Column(**raw)
In [4]: col.name2
Out[4]: 'demo1'
In [5]: col.nameid
Out[5]: '2'
If one of the values is wrong, Pydantic would raise a validation error:如果其中一个值错误,Pydantic 将引发验证错误:
In [6]: raw = {"name2": 1, "nameid": True}
In [7]: col = Column(**raw)
...
ValidationError: 1 validation error for Column
nameid
string does not match regex "[0-9]+" (type=value_error.str.regex; pattern=[0-9]+)
Then you move up to each Column
's parent object:然后向上移动到每个
Column
的父 object:
{
"name1": "abc",
"surname": "asd",
"columns": [
{"name2": "demo1", "nameid": "2"},
],
}
which can then be represented as:然后可以表示为:
from pydantic import BaseModel, conlist
class Demo(BaseModel):
name1: str
surname: str
columns: conlist(Column, min_items=1) # See: https://pydantic-docs.helpmanual.io/usage/types/#arguments-to-conlist
where we reuse the previous Column
class definition, to say that the columns
attribute is a list of Column
's.我们重用了前面的
Column
class 定义,也就是说columns
属性是Column
的列表。 Pydantic can instantiate and validate each attribute of Column
under Demo
: Pydantic 可以在
Demo
下实例化和验证Column
的每个属性:
In [8]: raw
Out[8]: {'name1': 'abc', 'surname': 'asd', 'columns': [{'name2': 'demo1', 'nameid': '2'}]}
In [9]: demo = Demo(**raw)
In [11]: demo.name1
Out[11]: 'abc'
In [13]: demo.surname
Out[13]: 'asd'
In [14]: demo.columns
Out[14]: [Column(name2='demo1', nameid='2')]
In [15]: demo.columns[0].name2
Out[15]: 'demo1'
In [16]: demo.columns[0].nameid
Out[16]: '2'
Again, if any of the values are wrong (whether from the outer attributes or from the innermost attributes), Pydantic will raise a validation error:同样,如果任何值是错误的(无论是来自外部属性还是来自最内部的属性),Pydantic 将引发验证错误:
In [20]: raw
Out[20]: {'name1': 'abc', 'surname': None, 'columns': [{'name2': 'demo1', 'nameid': '2'}]}
In [21]: demo = Demo(**raw)
...
ValidationError: 1 validation error for Demo
surname
none is not an allowed value (type=type_error.none.not_allowed)
In [27]: raw
Out[27]: {'name1': 'abc', 'surname': 'asd', 'columns': [{'name2': None, 'nameid': '2'}]}
In [28]: demo = Demo(**raw)
...
ValidationError: 1 validation error for Demo
columns -> 0 -> name2
none is not an allowed value (type=type_error.none.not_allowed)
Then after that, you move up again to each Demo
's parent object然后,您再次向上移动到每个
Demo
的父 object
{
"name": "suzuki",
"colors": "deq",
"demo": [
{
"name1": "abc",
"surname": "asd",
"columns": [
{"name2": "demo1", "nameid": "2"},
],
}
],
}
which can be represented as可以表示为
from pydantic import BaseModel, conlist
class Car(BaseModel):
name: str
colors: str
demo: conlist(Demo, min_items=1)
where, same as what we did for Column
, we have a demo
attribute that is modeled as a list of Demo
objects.其中,与我们为
Column
所做的一样,我们有一个demo
属性,它被建模为Demo
对象列表。 Pydantic can handle nested initialization and validation of demo
which includes its inner Column
class. Pydantic 可以处理
demo
的嵌套初始化和验证,其中包括其内部Column
class。
Finally, you'll reach the uppermost object:最后,您将到达最上面的 object:
test1 = {
"abx": [
{...},
{...},
]
}
which has an abx
attribute that's a list of Car
objects它有一个
abx
属性,它是Car
对象的列表
from pydantic import BaseModel, conlist
class Test(BaseModel):
abx: conlist(Car, min_items=1)
In [3]: obj = Test(**test1)
In [4]: obj
Out[4]: Test(abx=[Car(name='toyota', colors='abc', demo=[Demo(name1='pqr', surname='abc', columns=[Column(name2='demo', nameid='1')])]), Car(name='suzuki', colors='deq', demo=[Demo(name1='abc', surname='asd', columns=[Column(name2='demo1', nameid='2')])])])
In [5]: obj.abx[1]
Out[5]: Car(name='suzuki', colors='deq', demo=[Demo(name1='abc', surname='asd', columns=[Column(name2='demo1', nameid='2')])])
In [6]: obj.abx[1].demo[0]
Out[6]: Demo(name1='abc', surname='asd', columns=[Column(name2='demo1', nameid='2')])
You can also stop modeling anywhere, for example, stop at modeling a Car
and validate from the raw abx
object:您还可以在任何地方停止建模,例如,停止建模
Car
并从原始abx
object 进行验证:
In [15]: car1 = Car(**test1['abx'][0])
In [16]: car1
Out[16]: Car(name='toyota', colors='abc', demo=[Demo(name1='pqr', surname='abc', columns=[Column(name2='demo', nameid='1')])])
In [17]: car2 = Car(**test1['abx'][1])
In [18]: car2
Out[18]: Car(name='suzuki', colors='deq', demo=[Demo(name1='abc', surname='asd', columns=[Column(name2='demo1', nameid='2')])])
Again, if you have an error, even somewhere in the inner Column
model, you'll get a validation error.同样,如果您有错误,即使在内部
Column
model 的某个地方,您也会收到验证错误。
The good thing about this is that you can test and validate each object in turn, from the innermost ones up to the outermost one.这样做的好处是您可以从最里面到最外面依次测试和验证每个 object。 For more details about the usage of
constr
and conlist
, check Pydantic docs for Constrained Types as well as the other Field Types and Validators for more complex validations.有关
conlist
constr
的更多详细信息,请查看 Pydantic 文档中的约束类型以及其他字段类型和验证器以获取更复杂的验证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.