[Python] El uso de Json Schema [original]

I. Antecedentes

Cuando trabajaba antes en un sistema de publicación de contenedores, era necesario verificar el deployment.yaml enviado durante la implementación. Aunque deployment.yaml se puede analizar como Json, se requiere la siguiente verificación cuando se enfrenta a muchas verificaciones de parámetros. Parece estar abrumado :

aaa = request.get('aaa', '')
if not aaa:
    return False, 'aaa不能为空'

bbb = request.get('bbb', 0)
if not bbb:
    return False, 'bbb不能为空'

if bbb > 10 or bbb < 1:
    return False, 'bbb必须在1-10之间'

En este momento, estoy buscando un método o una biblioteca disponible que pueda manejar una gran cantidad de validación de parámetros, y Json Schema simplemente encaja.

2. Resumen

Json Schema es una herramienta para definir la estructura de datos Json y verificar el contenido de datos Json según el formato Json. La documentación oficial proporciona muchos ejemplos. Por ejemplo, Json Schema proporciona anyOf, allOf, oneOf, not y otras reglas de combinación para reglas de validación estrictas.


En primer lugar, debe comprender el tipo de datos de Json:

# 对象,object
{
    
    "key1": "value1", "key2": 22}

# 数组/列表,array
["first", "second", "third"]

# 数字,number
42
3.1415

# 字符串,string
"Hello World"

# 布尔值,boolean
true
false

# null值,null
null

Por ejemplo, un ejemplo en formato json:

{
    
    
 "fruits": ["apple", "orange", "pear"],
 "vegetables": [
   {
    
    
     "veggieName": "potato",
     "veggieLike": true
   },
   {
    
    
     "veggieName": "broccoli",
     "veggieLike": false
   }
 ]
}

3. Introducción

JSON Schema define la especificación del formato JSON, y varios idiomas tienen bibliotecas de verificación de JSON Schema de terceros de código abierto, como gojsonschema de Go language, jsonschema de Python, etc.


De esta forma, podemos definir un esquema JSON, y luego cada módulo del sistema puede reutilizar esta especificación JSON, y el esquema JSON de datos que no cumpla con las reglas informará directamente un error.


La última versión de Json Schema es el borrador 8, que se lanzó en septiembre de 2019.


JSON Schema, como el estilo estándar de JSON, también tiene un conjunto de sintaxis de clave-valor para declarar varias reglas.


Las palabras clave comunes en Json Schema son:

palabras clave describir
$esquema Indica la especificación y la versión utilizada por el archivo JSON Schema, que se puede excluir. Nota: las diferentes versiones no son totalmente compatibles
identificación de $ El identificador de identificación único del esquema actual, que generalmente apunta a un nombre de dominio autónomo. Para la conveniencia de una referencia posterior, puede no incluir
título Proporcione un encabezado para este archivo de esquema JSON, opcional
descripción Información de descripción sobre el archivo de esquema JSON, opcional
escribe Indica el tipo de elemento a verificar. Por ejemplo, el tipo más externo indica que el objeto a verificar es un objeto JSON (objeto).
El tipo interno indica el tipo de elemento a verificar: entero, cadena, número, booleano, objeto, matriz, nulo
propiedades Describe qué propiedades/campos tiene el objeto JSON
enumeración Tipos de enumeración, como solo estos tipos: ["rojo", "ámbar", "verde"]
requerido Campos que deben estar presentes
mínimo Se utiliza para restringir el rango de valores, lo que indica que el rango de valores debe ser mayor o igual que el mínimo
exclusivo Mínimo Si el mínimo y el mínimo exclusivo existen al mismo tiempo, y el valor de mínimo exclusivo es verdadero, significa que el rango de valores solo puede ser mayor que el mínimo
máximo Se utiliza para restringir el rango de valores, lo que indica que el rango de valores debe ser menor o igual que el máximo
exclusivoMáximo Si tanto el máximo como el máximo exclusivo existen, y el valor de máximo exclusivo es verdadero, significa que el rango de valores solo puede ser menor que el máximo
multipleOf Se utiliza para restringir el valor, lo que indica que el valor debe ser divisible por el valor especificado por multipleOf
longitud máxima/longitud mínima Longitud máxima/mínima de datos de tipo cadena
dependencias Dependencias de campo, como:
{ "tipo":"objeto",  "propiedades":{    "nombre":{"tipo":"cadena"},    "edad":{"tipo":"número"} }, " dependencias":{ "género":["edad"] } } significa: el género depende de la existencia de la edad, se informará un error si el campo de edad no existe pero sí el campo de género






patrón Use expresiones regulares para restringir datos de tipo cadena, como: ^(\([0-9]{3}\))?[0-9]{3}-[0-9]{4}$
multipleOf Los múltiplos, como { "tipo": "número", "multipleOf": 5 } significa: el campo debe ser un múltiplo de 5
no Negativo, por ejemplo: { "no": { "tipo": "cadena" } }, no es una cadena
formación formación
uno de Satisfaga uno de ellos, por ejemplo: { "oneOf": [   { "type": "number", "multipleOf": 5 },   { "type": "number", "multipleOf": 3 } ] } significa 5 múltiplos o múltiplos de 3





todo Debe estar satisfecho, el uso es similar al de arriba
artículos únicos En la matriz, valor booleano que indica si el elemento de la matriz es único
minProperties/maxProperties En el objeto, indica el número mínimo/máximo de campos en el objeto
maxItems / minItems Indica el número máximo/mínimo de elementos en la matriz
longitud mínima/longitud máxima 字符串类型数据的最小/最大长度

官网一个示例来进行介绍:

{
    
    
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    
    
    "productId": {
    
    
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
    
    
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
    
    
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
    
    
      "description": "Tags for the product",
      "type": "array",
      "items": {
    
    
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "dimensions": {
    
    
      "type": "object",
      "properties": {
    
    
        "length": {
    
    
          "type": "number"
        },
        "width": {
    
    
          "type": "number"
        },
        "height": {
    
    
          "type": "number"
        }
      },
      "required": [ "length", "width", "height" ]
    }
  },
  "required": [ "productId", "productName", "price" ]
}

进行具体的分析说明:

# 说明当前使用的schema版本,可以不包含
"$schema": "http://json-schema.org/draft-07/schema#",

# 当前schema的唯一id标识,一般指向一个自主域名。方便后续引用,可以不包含
"$id": "http://example.com/product.schema.json",

# 当前schema的标题,简要描述信息,可不包含
"title": "Product",

# 详细描述信息,可不包含
"description": "A product from Acme's catalog",

# 约束对象是object,也就是在 properties{ } 中的数据
"type": "object",

# object中具体属性的约束,description是描述信息,不产生具体约束。type约束productid属性类型为整型
"properties": {
    
    
    "productId": {
    
    
      "description": "The unique identifier for a product",
      "type": "integer"
    },

# 约束price属性类型为数字型,可以是整型或浮点型。exclusiveMinimum约束该数字>0(不包含0)
    "price": {
    
    
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },

# 约束tag属性是array数组。items是数组项约束(即数组里面的每个元素),这里约束数组项均为字符型,minItems数组至少包含1项,uniqueItems约束数组中每项不得重复
    "tags": {
    
    
      "description": "Tags for the product",
      "type": "array",
      "items": {
    
    
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    },
  
# 约束dimensions嵌套对象,其中length,width,height均为数字类型,且这三个字段在dimensions对象中必须包含
 "dimensions": {
    
    
      "type": "object",
      "properties": {
    
    
        "length": {
    
    
          "type": "number"
        },
        "width": {
    
    
          "type": "number"
        },
        "height": {
    
    
          "type": "number"
        }
      },
  "required": [ "length", "width", "height" ]
    }

# 当前数据对象必须包含productId,productName,price三个字段
 "required": [ "productId", "productName", "price" ]
}

四、Python中使用

注意:不止Python语言,很多语言都有开源的第三方JSON Schema校验库,例如Go语言的gojsonschema,Python的jsonschema等。


以Python为例:


A. 先安装Json Schema依赖包

pip install jsonschema

B. 编写schema内容(一般是会将该内容写到json文件里面去然后读取)

schema = {
    
    
    "title": "test demo",
    "description": "validate result information",
    "type": "object",
    "properties": {
    
    
        "code": {
    
    
            "description": "error code",
            "type": "integer"
        },
        "msg": {
    
    
            "description": "error msg ",
            "type": "string"
        },
        "token":
        {
    
    
            "description": "login success return token",
            "maxLength": 40,
            "pattern": "^[a-f0-9]{40}$",  # 正则校验a-f0-9的16进制,总长度40
            "type": "string"
        }
    },
    "required": [
        "code", "msg", "token"
    ]
}

表示:

  • 包含字段:code、msg、token
  • code必须是整数
  • msg必须是字符串
  • token必须是字符串,最大长度为40,且只有a-f0-9这几个字符

C. 进行校验

from jsonschema import validate, draft7_format_checker
from jsonschema.exceptions import SchemaError, ValidationError

result = {
    
    
    "code": 0,
    "msg": "login success!",
    "token": "000038efc7edc7438d781b0775eeaa009cb64865",
    "username": "test"
}

try:
    validate(instance=result, schema=schema, format_checker=draft7_format_checker)
    except SchemaError as e:
        return 1, "验证模式schema出错,出错位置:{},提示信息:{}".format(" --> ".join([i for i in e.path if i]), e.message)
    except ValidationError as e:
        return 1, "不符合schema规定,出错字段:{},提示信息:{}".format(" --> ".join([i for i in e.path if i]), e.message)
    else:
        return 0, 'success'

validate 校验成功时候,不会有报错

  • JSON 数据校验失败,抛出 jsonschema.exceptions.ValidationError 异常
  • schema 模式本身有问题,抛出 jsonschema.exceptions.SchemaError 异常

五、例子

校验kubnetets的deployment:

{
    
    
    "title": "k8s deployment schema",
    "description": "check k8s deployment",
    "type": "object",
    "properties": {
    
    
        "apiVersion": {
    
    
            "type": "string"
        },
        "kind": {
    
    
            "type": "string",
            "enum": ["Deployment"]
        },
        "metadata": {
    
    
            "type": "object",
            "properties": {
    
    
                "name": {
    
    
                    "type": "string"
                },
                "labels": {
    
    
                    "type": "object"
                }
            },
            "required": ["name", "labels"]
        },
        "spec": {
    
    
            "type": "object",
            "properties": {
    
    
                "replicas": {
    
    
                    "type": "number",
                    "minimum": 1,
                    "maximum": 100
                },
                "selector": {
    
    
                    "type": "object"
                },
                "template": {
    
    
                    "type": "object",
                    "properties": {
    
    
                        "metadata": {
    
    
                            "type": "object"
                        },
                        "spec": {
    
    
                            "type": "object",
                            "properties": {
    
    
                                "containers": {
    
    
                                    "type": "array",
                                    "items": {
    
    
                                        "type": "object",
                                        "properties": {
    
    
                                            "name": {
    
    
                                                "type": "string"
                                            },
                                            "livenessProbe": {
    
    
                                                "type": "object"
                                            }
                                        },
                                        "required": ["name", "livenessProbe"]
                                    }
                                },
                                "nodeSelector": {
    
    
                                    "type": "object"
                                },
                                "volumes": {
    
    
                                    "type": "array",
                                    "items": {
    
    
                                        "type": "object",
                                        "properties": {
    
    
                                            "hostPath": {
    
    
                                                "type": "object"
                                            },
                                            "name": {
    
    
                                                "type": "string"
                                            }
                                        },
                                        "required": ["hostPath", "name"]
                                    }
                                }
                            },
                            "required": ["containers", "nodeSelector", "volumes"]
                        }
                    },
                    "required": ["metadata", "spec"]
                }
            },
            "required": ["replicas", "selector", "template"]
        }
    },
    "required": ["apiVersion", "kind", "metadata", "spec"]
}

即:


apiVersion、kind、metadata、spec必填

其中:

  • apiVersion:字符串
  • kind:必须为Deployment
  • metadata:object
  • spec:object

metadata下name、labels必填

其中:

  • name:字符串
  • labels:object

spec下的replicas、selector、template必填

其中:

  • replicas:数字,且1-100之间
  • selector:object
  • template:object

spec 下的 template 下的metadata、spec必填

其中:

  • metadata:object
  • spec:object

spec 下的 template 下的 spec 下的containers、nodeSelector、volumes必填

其中:

  • containers:数组
  • nodeSelector:object
  • volumes:数组

spec 下的 template 下的 spec 下的 containers 下的每个元素,为object,必须包含name、livenessProbe

其中:

  • name:字符串
  • livenessProbe:object

spec 下的 template 下的 spec 下的 volumes 下的每个元素,为object,必须包含name、hostPath

其中:

  • name:字符串
  • hostPath:object

更多的例子可参考:

六、参考

Supongo que te gusta

Origin blog.csdn.net/jiandanokok/article/details/109883741
Recomendado
Clasificación