py3筆記8:json&json結(jié)構(gòu)的校驗(yàn)

1. Json模塊

python中使用json模塊實(shí)現(xiàn)python對(duì)象與json的轉(zhuǎn)換

  • json.dumps():Python對(duì)象轉(zhuǎn)換為Json Object(JSON字符串)
  • json.loads() :Json對(duì)象(已編碼的JSON字符串)轉(zhuǎn)換為python 對(duì)象
    Python 編碼為 JSON 類型轉(zhuǎn)換對(duì)應(yīng)表:
    image.png

    JSON 解碼為 Python 類型轉(zhuǎn)換對(duì)應(yīng)表:
    image.png
import json

res = {"success": True,
       "code": "200",
       "msg": None,
       "data": [{"belongEndCode": "EMBEDDED", "belongEndDesc": "嵌入式"},
                {"belongEndCode": "PANEL", "belongEndDesc": "面板"},
                {"belongEndCode": "CLOUD", "belongEndDesc": "云端"},
                {"belongEndCode": "IOS", "belongEndDesc": "iOS"},
                {"belongEndCode": "SMALL_PROGRAM", "belongEndDesc": "小程序"},
                {"belongEndCode": "WEB", "belongEndDesc": "Web前端"}],
       "t": 1648869618886}

json_res = json.dumps(res, ensure_ascii=False) 
print(json_res)
print(type(json_res))  # <class 'str'>
# 對(duì)python而言,實(shí)際是json編碼的字符串
1.1 dumps的參數(shù)
  1. ensure_ascii=False, 則返回結(jié)果不含ascII字符,解決中文亂碼問(wèn)題。
  2. sort_keys是告訴編碼器按照字典key排序(a到z)輸出。
json_res = json.dumps(res, ensure_ascii=False, sort_keys=True)  # 添加sort_keys的傳參
#輸出結(jié)果
{"code": "200", "data": [{"belongEndCode": "EMBEDDED", "belongEndDesc": "嵌入式"}, {"belongEndCode": "PANEL", "belongEndDesc": "面板"}, {"belongEndCode": "CLOUD", "belongEndDesc": "云端"}, {"belongEndCode": "IOS", "belongEndDesc": "iOS"}, {"belongEndCode": "ANDROID", "belongEndDesc": "Android"}, {"belongEndCode": "SMALL_PROGRAM", "belongEndDesc": "小程序"}, {"belongEndCode": "H5", "belongEndDesc": "H5"}, {"belongEndCode": "WEB", "belongEndDesc": "Web前端"}, {"belongEndCode": "PC", "belongEndDesc": "PC端"}], "msg": null, "success": true, "t": 1648869618886}
  1. indent參數(shù)根據(jù)數(shù)據(jù)格式縮進(jìn)顯示,讀起來(lái)更加清晰, indent的值,代表縮進(jìn)空格式
json_res = json.dumps(res, ensure_ascii=False, sort_keys=True, indent=4)  # 添加indent,一般使用4代表一個(gè)Tab鍵的縮進(jìn)
# 輸出結(jié)果:
{
    "code": "200",
    "data": [
        {
            "belongEndCode": "CLOUD",
            "belongEndDesc": "云端"
        },
        {
            "belongEndCode": "PC",
            "belongEndDesc": "PC端"
        }
    ],
    "msg": null,
    "success": true,
    "t": 1648869618886
}
  1. skipkeys參數(shù),在encoding過(guò)程中,dict對(duì)象的key只可以是string對(duì)象,如果是其他類型,那么在編碼過(guò)程中就會(huì)拋出ValueError的異常。skipkeys可以跳過(guò)那些非string對(duì)象當(dāng)作key的處理.
    skipkeys
1.2 json文件

要處理的是文件而不是字符串,你可以使用json.dump()json.load() 來(lái)編碼和解碼JSON數(shù)據(jù)

# 寫入 JSON 數(shù)據(jù)
with open('data1.json', 'w', encoding="utf-8") as f:
    json.dump(res, f)  # res為python對(duì)象

# 讀取數(shù)據(jù)
with open('data1.json', 'r', encoding="utf-8") as f:
    data = json.load(f)

2. JsonSchema

Json Schema是一個(gè)用于驗(yàn)證Json數(shù)據(jù)結(jié)構(gòu)的強(qiáng)大工具
使用范圍:接口測(cè)試中數(shù)據(jù)值校驗(yàn)、數(shù)據(jù)類型校驗(yàn)、json數(shù)據(jù)結(jié)構(gòu)校驗(yàn)
官網(wǎng):https://json-schema.org/understanding-json-schema/conventions.html
安裝:pip install jsonschema

2.1 type關(guān)鍵字

type 關(guān)鍵字是json模式的基礎(chǔ),指定架構(gòu)的數(shù)據(jù)類型:string、number、object、array、boolean、null

from jsonschema import validate
# json.dumps中indent存在是,校驗(yàn)json_schema也不通過(guò)
# json.dumps中sort_keys存在時(shí),排序也會(huì)影響校驗(yàn)結(jié)果
# 不需要將python對(duì)象dumps成json

res = 1
json_schema = {"type": "string"}
validate(res, json_schema)  # 校驗(yàn),若不匹配則報(bào)錯(cuò)
# jsonschema.exceptions.ValidationError: instance is not of type 'xxx'

# 多個(gè)類型
res = 2
json_schema = {"type": ["string", "object"]}
validate(res, json_schema)  # 校驗(yàn),若不匹配則報(bào)錯(cuò)
# jsonschema.exceptions.ValidationError: 2 is not of type 'string', 'object'

2.2 object關(guān)鍵字

object關(guān)鍵字,在python中對(duì)應(yīng)的是dict類型

  • 屬性properties
    用于定對(duì)象上的屬性(即dict的鍵)
res = {
    "code": "200",
    "data": [{"name": 123}, {"name", 3}],
    "msg": None,
    "success": True,
    "t": 1648869618886
}
json_schema = {
    "type": "object",
    "properties": {
        "code": {"type": "string"},
        "data": {"type": "array"},
        "msg": {"type": "null"},
        "success": {"type": "boolean"},
        "t": {"type": "number"}
    }
}
validate(res, json_schema)
  • 必需屬性required
    properties不需由關(guān)鍵字定義的屬性,也可以使用required關(guān)鍵字來(lái)提供所需屬性的列表
    required 接受一個(gè)或多個(gè)字符串的數(shù)組。且每個(gè)字符串必須是唯一的。
res = {
    "code": "200",
    "data": [{"name": 123}, {"name", 3}],
    "msg": None,
    "success": True,
    "t": 1648869618886
}
json_schema = {
    "type": "object",
    "required": ["t", "msg"]
}
validate(res, json_schema)
# 必需屬性的缺失會(huì)報(bào)錯(cuò):jsonschema.exceptions.ValidationError: 'datas' is a required property
# 必需參數(shù)不校驗(yàn)屬性的排序
  • 屬性數(shù) minPropertiesmaxProperties
    限制對(duì)象上的屬性數(shù)。這些中的每一都必需是非負(fù)整數(shù)
json_schema = {
    "type": "object",
    "minProperties": 4,  # 最少
    "maxProperties": 5 # 最多
}
validate(res, json_schema)
# 報(bào)錯(cuò)信息:jsonschema.exceptions.ValidationError: xxx has too many properties 或 xxx does not have enough properties

2.3 array關(guān)鍵字

數(shù)組屬性array,用于有序元素
在python中,array類似于list或tuple

  • items
    數(shù)組的元素,可能是任何類型,但根據(jù)某模式驗(yàn)證數(shù)組的項(xiàng)通常很有用。使用itemsadditionalItems關(guān)鍵字來(lái)完成
    items 是單個(gè)模式,針對(duì)數(shù)組中每一個(gè)項(xiàng)目而言

在Json,通常有2種方式驗(yàn)證
1. 列表驗(yàn)證:任意長(zhǎng)度的序列,其中每個(gè)元素匹配相同的模式
2. 元組驗(yàn)證:一個(gè)固定長(zhǎng)度的序列,其中每個(gè)項(xiàng)目可能具有不同的模式

# res = [1, "2", [3], {"f": 4}, (5,)]
res = [1, "2", [3], {"f": 4}]
# print(type(res[4]))  # <class 'tuple'>

1. 列表驗(yàn)證

res = [1, 2, 3, 4, 5]
 json_schema = {
     "type": "array",
     "items": {"type": "number"}
}
 validate(res, json_schema)
# 不匹配報(bào)錯(cuò):jsonschema.exceptions.ValidationError: '2' is not of type 'number'

2. 元組驗(yàn)證
針對(duì)每一個(gè)元素解釋說(shuō)明,默認(rèn)校驗(yàn)schema中設(shè)置的前n項(xiàng)
將items關(guān)鍵字設(shè)置成一個(gè)數(shù)組, 其中每個(gè)項(xiàng)目都是一個(gè)與文檔數(shù)組的每個(gè)索引相對(duì)應(yīng)的模式,
也就是一個(gè)數(shù)組, 第一個(gè)元素模式驗(yàn)證輸入數(shù)組的第一個(gè)元素. 第二個(gè)元素模式驗(yàn)證輸入數(shù)組的第二個(gè)元素

json_schema = {
     "type": "array",
     "items": [
         {"type": "number"},
         {"type": "string"},
         {"type": "array", "items": {"type": "number"}},
         {"type": "object"},
         {"type": "string"}    # python中tuple對(duì)應(yīng)的是json中的??
     ]
 }
 validate(res, json_schema)
  • additionlItems 關(guān)鍵字
    控制是否有超出schema中定義的數(shù)組的其他項(xiàng),默認(rèn)True;若設(shè)置為False,則不允許數(shù)組中的額外項(xiàng)
res = [1, "2", [3], {"f": 4}, "5", (6,)]
# validate(res, json_schema)  # 默認(rèn)True,允許數(shù)組中額外項(xiàng)
json_schema = {
    "type": "array",
    "items": [
        {"type": "number"},
        {"type": "string"},
        {"type": "array", "items": {"type": "number"}},
        {"type": "object"}
    ],
    "additionalItems": False
}
# validate(res, json_schema)
# 校驗(yàn)不通過(guò),則報(bào)錯(cuò)jsonschema.exceptions.ValidationError: Additional items are not allowed ('5', (6,) were unexpected)
  • 長(zhǎng)度minItemsmaxitems
    每個(gè)關(guān)鍵字的值都必須是非負(fù)數(shù)。無(wú)論是對(duì)List還是tuple驗(yàn)證,這些字段都是有效的
json_schema = {
    "type": "array",
    "minItems": 3,
    "maxItems": 3
}
validate(res, json_schema)
# 校驗(yàn)失敗,報(bào)錯(cuò):jsonschema.exceptions.ValidationError: xxx is too short 或 xxx is too long
  • 唯一性uniqueItems
res = [1, 1, 2]
json_schema = {
    "type": "array",
    "uniqueItems": True
}
validate(res, json_schema)
# 存在重復(fù)數(shù)據(jù)時(shí),報(bào)錯(cuò):jsonschema.exceptions.ValidationError: xxx has non-unique elements

2.4 通用關(guān)鍵字

  • 元數(shù)據(jù)
    json模式包含幾個(gè)關(guān)鍵字, title, descriptiondefault, 不嚴(yán)格用來(lái)校驗(yàn)格式,但用來(lái)描述模式的一部分。
    在title和description管家你必須是字符串

  • 枚舉值enum
    enum關(guān)鍵字用于限制值, 以一個(gè)固定的一組值, 它必須是一個(gè)必須包含一個(gè)元素的數(shù)組,其中每個(gè)元素都是唯一的。

{ 
  ‘type’ : ‘string’, 
  ‘enum’: [‘red’, ‘green’] 
}
# 如果檢驗(yàn)字段的值在枚舉中是通過(guò)的, 如果不是無(wú)法校驗(yàn)通過(guò)。

2.5 組合模式

例如, 在以下的模式, anyOf關(guān)鍵字用于表示給定值可能對(duì)任何給定的子模式有效。第一個(gè)子模式需要一個(gè)最大長(zhǎng)度為5的字符串。第二個(gè)子模式需要一個(gè)最小值為0的數(shù)字。只要一個(gè)值對(duì)這些模式中的任何一個(gè)進(jìn)行驗(yàn)證,它就被認(rèn)為整個(gè)組合模式有效。
{ ‘a(chǎn)nyOf’: [ {‘type’: ‘string’, ‘maxLength’: 5}, {‘type’:’string’, ‘minimum’: 0 }]}

用于組合模式的關(guān)鍵字是:

  • anyOf: 必須對(duì)任何子模式有效(一個(gè)或多個(gè))
  • oneOf: 必須僅對(duì)其中一個(gè)子模式有效
  • allOf: 必須對(duì)所有子模式有效
  • anyOf
    要進(jìn)行驗(yàn)證anyOf,給定數(shù)據(jù)必須對(duì)任何(一個(gè)或多個(gè))給定子模式有效。
{
  “anyOf” : [
    { “type” : “string” },
    { “type” : “number” }
  ]
}
# 如果是 “您好”, pass 
# 如果是 33, pass 
# 如果是 [‘ddd’, 33], false
等同于 
{
 “type” :[ “string” ,“number” ]
}
  • oneOf
    要進(jìn)行驗(yàn)證oneOf,給定數(shù)據(jù)必須僅對(duì)其中一個(gè)給定子模式有效。
{
  “oneOf” : [
    { “type” : “number” , “multipleOf” : 5 },
    { “type” : “number” , “multipleOf” : 3 }
  ]  
}
如果是5的倍數(shù), pass 
如果是3的倍數(shù), pass 
如果是5和3的倍數(shù), false
  • allOf
    要進(jìn)行驗(yàn)證allOf,給定數(shù)據(jù)必須對(duì)所有給定的子模式有效。
{
  “allOf” : [
    { “type” : “string” },
    { “maxLength” : 5 }
  ]
}

2.6 $schema關(guān)鍵字

該$schema關(guān)鍵字用于聲明JSON片段實(shí)際上是JSON模式的一部分。它還聲明了針對(duì)該模式編寫的JSON Schema標(biāo)準(zhǔn)的哪個(gè)版本。

建議所有JSON模式都有一個(gè)$schema條目,該條目必須位于根目錄下。因此,大多數(shù)情況下,您需要在架構(gòu)的根目錄下:

“$ schema” : “http://json-schema.org/schema#


3. 參考

  1. jsonschema+裝飾器 實(shí)現(xiàn)更簡(jiǎn)單的python參數(shù)校驗(yàn)
  2. JsonSchema使用詳解
  3. python3 json數(shù)據(jù)解析
  4. json.dumps參數(shù)說(shuō)明
  5. JSON Schema 規(guī)范文檔(中文版)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容