簡體   English   中英

如何在 python 中使用 Pydantic model 驗證 2 個嵌套的 json?

[英]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"
            }
          ]
        }
      ]
    }
  ]
}

我有 2 個嵌套的 JSON 並且兩個響應都有隨機播放值。 我想匹配使用 Pydantic 模型在 Python 中進行測試。

有什么方法可以比較、驗證兩個響應嗎?

嵌套的 JSON 可以簡單地用嵌套的 Pydantic 模型表示 每個 object 都可以映射到 model,並且 model 可以具有其他 Pydantic 模型或 Pydantic 模型列表的屬性。

你從最里面的對象開始:

{
    "name2": "demo1",
    "nameid": "2",
}

可以表示為:

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'

如果其中一個值錯誤,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]+)

然后向上移動到每個Column的父 object:

{
    "name1": "abc",
    "surname": "asd",
    "columns": [
        {"name2": "demo1", "nameid": "2"},
    ],
}

然后可以表示為:

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

我們重用了前面的Column class 定義,也就是說columns屬性是Column的列表。 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'

同樣,如果任何值是錯誤的(無論是來自外部屬性還是來自最內部的屬性),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)

然后,您再次向上移動到每個Demo的父 object

{
    "name": "suzuki",
    "colors": "deq",
    "demo": [
        {
            "name1": "abc",
            "surname": "asd",
            "columns": [
                {"name2": "demo1", "nameid": "2"},
            ],
        }
    ],
}

可以表示為

from pydantic import BaseModel, conlist

class Car(BaseModel):
    name: str
    colors: str
    demo: conlist(Demo, min_items=1)

其中,與我們為Column所做的一樣,我們有一個demo屬性,它被建模為Demo對象列表。 Pydantic 可以處理demo的嵌套初始化和驗證,其中包括其內部Column class。

最后,您將到達最上面的 object:

test1 = {
    "abx": [
        {...},
        {...},
    ]
}

它有一個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')])

您還可以在任何地方停止建模,例如,停止建模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')])])

同樣,如果您有錯誤,即使在內部Column model 的某個地方,您也會收到驗證錯誤。

這樣做的好處是您可以從最里面到最外面依次測試和驗證每個 object。 有關conlist constr的更多詳細信息,請查看 Pydantic 文檔中的約束類型以及其他字段類型驗證器以獲取更復雜的驗證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM