【Python】schema 和 jsonschema


schema (XSD)

  XML Schema 描述 XML 文档的结构。可以指定一个.xsd (xml schema) 验证某个xml

  作用:定义 XML 文档的合法构建模块,类似 DTD(文档类型定义)

  参考地址: https://www.w3school.com.cn/schema/index.asp

  xml 了解:  

 声明





<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://www.w3school.com.cn"  
xmlns="http://www.w3school.com.cn" 
elementFormDefault="qualified" 
>
    
    <xs:element name="name"  type="xs:string"/>
xs:schema>

数据类型

拓展

属性


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
    
    <xs:attribution name = "attr" type="xs:string" use="required"/>
    
    <name attr="EN">lucyname>
xs:schema>

简易元素

  只有元素本身,不包含其他元素


<xs:element name="xxx" type="yyy" default="name"/> <xs:element name="color" type="xs:string" fixed="name"/>

 

限定

取值范围限定

  
    <xs:element name="age">
    
        
        <xs:simpleType>
        
                
            <xs:restriction base="xs:integer">
            
                
                <xs:minInclusive value="18"/>
                
                <xs:maxInclusive value="60"/>
                
            
            xs:restriction>
            
        
        xs:simpleType>
    
    
    <xs:element/>

枚举限定

    <xs:element name="idName">
        
        <xs:simpleType>
                
            <xs:restriction base="xs:string">
            
                
                <xs:enumeration value="zhangsan"/>
                <xs:enumeration value="lisi"/>
                <xs:enumeration value="wangwu"/>
                
            xs:restriction>
        xs:simpleType>
    xs:element>

模式限定

    <xs:element name="enName">
               
        <xs:simpleType>
            
                 
            <xs:restriction base="xs:string">
            
                
                <xs:pattern value="[A-Z][a-z][a-z]"/>
                
                <xs:pattern value="[0-9][0-9][0-9][0-9][0-9]"/>
                
                <xs:pattern value="[xyz]"/>
                
                <xs:pattern value="([a-z])*"/>
                
                <xs:pattern value="([a-z][A-Z])+"/>
                
                <xs:pattern value="men|women"/>
                
                <xs:pattern value="[a-zA-Z0-9]{8}"/>
                
            xs:restriction>
            
        xs:simpleType>
    xs:element>

空白字符限定

    <xs:element name="addr">
        
        <xs:simpleType>
            
                 
            <xs:restriction base="xs:string">
            
                
                <xs:whiteSpace value="preserve"/>
                
                
                <xs:whiteSpace value="replace"/>
                
                
                <xs:whiteSpace value="collapse"/>
                
            xs:restriction>
            
        xs:simpleType>
xs:element>

长度限定

    <xs:element name="phone">
        
        <xs:simpleType>
            
                 
            <xs:restriction base="xs:string">
            
                
                <xs::length value="11"/>
                
                
                <xs:minLength value="7"/>
                <xs:maxLength value="11"/>
                            
            xs:restriction>
            
        xs:simpleType>

    xs:element>
    <xs:element name="score">

        
        <xs:simpleType>
        
                
            <xs:restriction base="xs:string">
            
                
                <xs::length value="8"/>
                
                
                <xs:fractionDigits value="2"/>
                
                
            xs:restriction>
            
        xs:simpleType>

    xs:element>

复合元素


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
        
    <xs:element name="Name">
    
        
        <xs:complexType>
            <xs:sequence>
                <xs:element name="idName" type="xs:string"/>
                <xs:element name="custName" type="xs:string"/>
            xs:sequence> 
        xs:complexType>
        
    xs:element>
    

xs:schema>

数据类型限定

  Order指示器

        
        <xs:complexType>
        
            
            <xs:all>
                <xs:element name="idName" type="xs:string"/>
                <xs:element name="custName" type="xs:string"/>
            xs:all>
    xs:complexType>
       
            <xs:Choice >
                <xs:element name="idName" type="xs:string"/>
                <xs:element name="custName" type="xs:string"/>
            xs:Choice >
       
            <xs:sequence>
                <xs:element name="idName" type="xs:string"/>
                <xs:element name="custName" type="xs:string"/>
            xs:sequence>

 


"http://www.w3.org/2001/XMLSchema">
    
    "response">
        
          "1">
            "content" type="xs:string"/>
            
            "respCode" minOccurs="0">
                
                  "xs:string">
                    
                    "0000"/>
                    
                    "9999"/>
                  
                
            

            "respMsg" type="xs:string"/>
          
        
    
XSD

jsonschema

  Json Schema 描述 Josn 文档的结构。

  官方版本参考: https://json-schema.org/specification-links.html

  jsonschema参考地址:https://www.freesion.com/article/7617866008/

jsonschema 组成结构

声明版本

# $schema 声明了针对该架构编写的JSON Schema标准版本
"$schema": "http://json-schema.org/draft-04/schema#",

文档标题

# title 文档标题,关键字是描述性的,用来对文档作补充说明
"title": "respMsg schema",

文档描述

# description 文档描述,关键字是描述性的,用来对文档作补充说明
"description": "validate result information",

字段描述

# default 描述字段 非必须字段
# "default":{}
"default": "描述字段"
"example": "描述字段(in draft 6),用于展示转换前的json; "
$comment: "描述字段(in draft 7 用于 schema 开发人员对文档进行注释,不需要展示给最终用户看。)"
{
    // 声明
    "$schema": "http://json-schema.org/draft-04/schema#",
    // 标题
    "title":"Message",
    // 描述
    "description":"validata information",

}
示例

type类型

   

  Object 对象

{
    // 声明
    "$schema": "http://json-schema.org/draft-04/schema#",
    // 标题
    "title":"Message",
    // 描述
    "description":"validata information",

    // 类型 对象object
    "type":"object",

    //additionalProperties 默认true(允许properties之外的属性存在); false(不可以出现properties之外的属性)
    "additionalProperties":false,

    // required 存放必要属性列表
    "required":["respCode", "respMsg"]

    // object 出现的属性字段
    "properties":{
// string 字符串 "respCode":{"type": "string"} "respMsg":{"type": "string"} "failMsg":{"type": "string"} } // 属性数量最小值 "minProperties":2 // 属性数量最大值 "maxProperties":2 // dependencies 定义属性依赖值 "dependencies":{ // failMsg依赖于respMsg,当resoMsg存在时,failMsg才必须存在 "failMsg":["respMsg"] } }

  array 数组

{

    // 类型 数组 array
    "type":"array",
    
    // additionalItems默认true(允许items之外的项目存在); false(不可以出现items之外的项目)
    "additionalItems":false,
    
    // 针对数组中的所有元素类型进行验证,当数组中存在类型非string时。整个数组无效 (慎用)
    // "contains": {"type":"string"},

    // 验证数组中的所有元素的类型;每个元素都可以具有不同的类型,列表验证(任意长度的序列)和元组验证(固定长度的序列)
    "items":{
         // string 字符串
        "respCode":{"type": "string"}
        "respMsg":{"type": "string"}
        "failMsg":{"type": "string"}
    }
    // 非负数最小长度
    "minItems":2
    
    // 非负数最大长度
    "maxItems":2
        
    // 数组内元素唯一性验证 True 不能有重复元素
    "uniqueItems": false

}

  String 字符串

{

    // 类型 字符串 string
    "type":"string",
    
    // 字符串最大长度(包含)
    "maxLength":3,
    
    // 字符串最小长度(包含)
    "minLength":1,
    
    // 正则匹配字符串 示例:(xxx)xxx-xxxx x代表0-9的数字
    "pattern":"^(([0-9]{3}))?[0-9]{3}-[0-9]{4}$"
    
    // 指定MIME类型的字符串的内容 示例:包含一个HTML文档
    // "contentMediaType":"text/html",
    
    // 指定的编码用于存储内容 示例:使用Base64编码的PNG图像
    "contentEncoding":"base64",
    "contentMediaType":"image/png"
}

  number 数值(任何数字类型,整型或浮点型都可)

{

    // 类型 数值 number
    "type":"number",
    
    // 倍数 1的倍数
    // "multipleOf":1,
    
    // 最小值(包含)
    "minimum":1,
    
    // boolean不包含最小值 或 数值 开区间最小值
    "exclusiveMinimum":true,
    
    //最大值(包含)
    "maximum":999.99,
        
    // boolean不包含最大值 或 数值 开区间最大值
    "exclusiveMaximum":true
}

   

  integer 整型 (同number)

{

    // 类型整型
    "type":"integer",
    
    // 倍数 1的倍数
    // "multipleOf":1,
    
    // 最小值(包含)
    "minimum":1,
    
    // 不包含最小值
    "exclusiveMinimum":true,
    
    //最大值(包含)
    "maximum":999.99,
    
    
    // 不包含最大值
    "exclusiveMaximum":true
}

  boolean 布尔值

    仅包含true和false

  null 空值

    仅支持字段值为null

  any 任何值

    支持所有类型

  const 关键字验证

    验证值必须等于该常量,此关键字的值可以是任何类型,包括null。


  enum 枚举值  

    值只能是enum数组中的某一项 示例:["a", "b"]

   多类型

   判断 "if":{},"then":{},"else":{}

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title":"Message",
    "description":"validata information",

    "type":"object",
    "properties":{
        "name":{
            "type":"string",
        },
        "sex":{
            "enum":["man", "woman"]
        }
    },
    // 条件
    "if":{
        "properties":{"age":{"const":"man"}}
    },
    // 符合条件 stage值
    "then":{
        "properties":{"stage":{"enum":[""]}}
    },
    // 不符合条件 stage值
    "else":{
        "properties":{"stage":{"enum":[""]}}
    }    
}

验证schema

jsonSchema 校验

def resp_json_check(self, data, cmd):

    json_schema_pathname = os.path.dirname(os.getcwd()) + "\\schema\\schema_%s.json" % cmd
    try:
        with open(json_schema_pathname, 'r', encoding='utf-8') as f:
            json_doc = commentjson.loads(f.read())
    except Exception as e:
        logs.warning("未进行数据规则校验,发生异常原因:" + str(e) + "[请前往目录检查文件]")
        return False
    else:
        try:
            # validate校验, 跟assert断言一个意思
            validate(instance=eval(data), schema=json_doc, format_checker=draft7_format_checker)

        except SchemaError as e:
            logs.error("SchemaError:数据不符合规则,请检查数据or修改校验文件")
            error1 = "验证模式schema出错:\n出错位置:{}\n提示信息:{}".format("".join([str(i) for i in e.path]), e.message)
            logs.error(error1)
            return error1

        except ValidationError as e:
            logs.error("ValidationError:数据不符合规则,请检查数据or修改校验文件")
            error2 = "验证模式schema出错:\n出错位置:{}\n提示信息:{}".format("".join([str(i) for i in e.path]), e.message)
            logs.error(error2)
            return error2

        else:
            logs.info("基础校验 --> schema校验符合规则,验证通过!")
            return True

  

 xmlschema 校验

def resp_xsd_check(self, data):
    xml_doc = data
    xsd_schema_path = os.path.dirname(os.getcwd()) + "\\schema\\resp_xsd_check.xsd"
    
    try:
        with open(xsd_schema_path,encoding='utf-8') as f:
            xsd_doc = f.read()
    except Exception as e:
        logs.warning("未进行 xsd 数据规则校验,发生异常原因:" + str(e) + "[请前往目录检查文件]")
        return False
    else:
        xsd_doc_io = StringIO(xsd_doc)
        xsdCheck_doc = etree.parse(xsd_doc_io)

        xml_doc_io = StringIO(xml_doc)
        xmlschema = etree.XMLSchema(xsdCheck_doc)
        xmlCheck_doc = etree.parse(xml_doc_io)

        try:
            xmlschema.validate(xmlCheck_doc)
            xmlschema.assertValid(xmlCheck_doc)

        except lxml.etree.XMLSchemaParseError as xspe:
            logs.warning("XMLSchemaParseError occurred!" + str(xspe))
            return False

        except lxml.etree.XMLSyntaxError as xse:
            logs.warning("XMLSyntaxError occurred!" + str(xse))
            return False

        except lxml.etree.DocumentInvalid:
            logs.warning("xsd 数据不符合规则,请检查数据or完善文件")

            error = xmlschema.error_log.last_error
            if error:
                logs.error("异常原因:" + error.message)
                return False
            else:
                return True
        else:
            logs.info("xsd 数据符合规则,验证通过!")
            return True

拓展


1、UnicodeDecodeError:: 'utf-8' codec can't decode byte 0xc8 in position 0: invalid contin

  出现场景:读取json文件时报错

  问题原因:字符编码问题

    ASCII编码:大小写英文字母、数字和一些符号

    GB2312编码:收录汉字6763个,采用双字节编码。

    GBK编码:收录汉字21003个,采用双字节编码。

    GB18030编码:目前收录汉字70000余个,以及多种少数民族文字。采用单字节、双字节、四字节分段编码。

    Unicode编码:所有语言都统一到一套编码里,采用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。

    ASCII与Unicde转化:ASCII编码的数据用Unicode编码,只需要在前面补0就可以。

    bytes类型的数据用带b前缀的单引号或双引号表示

  解决方法:将json文件转换为需要读取的编码(utf-8模式(Notepad++ 设置 - 编码 - 使用utf-8编码)

2、