JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。
举个栗子:
{ "an": [ "arbitrarily", "nested" ], "data": "structure" }
参数检测是服务器端拿到参数的第一步操作,后续的一系列操作都完全信任数据的可靠安全性。可以准确的说,前端的参数校验是为了适当的保护服务端,为了更好的用户体验,但服务端万万不可信任前端传递的参数,所有的参数一定要进行校验,确保输入数据是合法正确性,这是服务端程序员的基本准则。常见的参数检验包括非空,最大长度检测,大小检测等等。应用在执行业务逻辑之前,必须通过校验保证接受到的输入数据是合法正确的,但很多时候同样的校验出现了多次,在不同的层,不同的方法上,导致代码冗余,浪费时间。
可以针对每个字段,进行一系列的参数校验,然后完成该json参数的检验。
举个栗子:
dict = { "an": [ "arbitrarily", "nested" ], "data": "structure" }
if dict.get(data, '')=='':
return 'key data is no null'
if len(dict.get(data, ''))>30:
return "data is too long"
other verify
就是这样不断的针对每一个字段进行校验,确保输入的数据的可靠、安全性。
缺点:很多时候同样的校验出现了多次,在不同的层,不同的方法上,导致代码冗余,浪费时间。比如校验是否为空,检验长度对大等等大量重复代码,效率很低。
相信用过flask-wtf的同学都会很喜欢这样的校验工具,自动对每个字段进行,而且效率还很高,不用写大量的重复代码,开发效率会得到大大的提升。反正我在用html的表单提交时都会使用flask-wtf,只能说,你用过一次就会爱上它。
那么当前端提交的数据不是form而是json时怎么办呢?如果不想像上面一样每个字段或者每个数据都一一检测,这时候你可以尝试使用json schema,很像flask-wtf的一个开源框架,专门用来校验json或者可以转换成json的dict。
先举个栗子,大致说一下json schema怎么用
>>> from jsonschema import validate
>>> # A sample schema, like what we'd get from json.load()
>>> schema = {
... "type" : "object",
... "properties" : {
... "price" : {"type" : "number"},
... "name" : {"type" : "string"},
... },
... }
>>> # If no exception is raised by validate(), the instance is valid.
>>> validate({"name" : "Eggs", "price" : 34.99}, schema)
>>> validate(
... {"name" : "Eggs", "price" : "Invalid"}, schema
... ) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...i
ValidationError: 'Invalid' is not of type 'number'
你可以使用validate来验证输入的json是否符合你需要的模式,如果不符合要求会抛出ValidationError异常,ValidationError.message 会提示不符合哪个要求或哪个要求出错,ValidationError.instance会提示是不符合该要求的字段的内容或者实例是什么。具体的schema 的表达式该怎么写后面会介绍到。
json schema的表达式在这里就讲点基本的好了,其实基本的已经够用了,如果要想更深入学习,可以到官网json schema进行学习。
json schema能支持的类型有string,Numeric types,object,array,boolean,null。接下来会一一解释。
举个例子来说明:
{
"type": "string",
"minLength": 2,
"maxLength": 3
}
'A' is wrong, 'aa' is ok, 'aaa' is ok ,'aaaasf' is wrong
这表明它需要一个string字段,其中string 有的属性有:
老惯例,上来举个例子:
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMaximum": true
}
ok:
0
10
99
wrong:
-1
100
101
这表明它需要一个Numeric types字段,其中number有的属性有:
在Python中,object类似于dict类型,”type”:”object”就是声明需要dict类。举个例子,就能大致理解了:
{
"type": "object",
"properties": {
"number": { "type": "number" },
"street_name": { "type": "string" },
"street_type": { "type": "string",
"enum": ["Street", "Avenue", "Boulevard"]
}
}
}
ok:
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }
{ "number": 1600, "street_name": "Pennsylvania" }
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }
wrong:
{ "number": "1600", "street_name": "Pennsylvania", "street_type": "Avenue" }
这表明它需要dict的类型。object具有的属性有:
{
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "string"
},
{
"type": "string",
"enum": ["Street", "Avenue", "Boulevard"]
},
{
"type": "string",
"enum": ["NW", "NE", "SW", "SE"]
}
]
}
则
[1600, "Pennsylvania", "Avenue", "NW"] is ok
“Drive” is not one of the acceptable street types:
[24, "Sussex", "Drive"] is wrong
This address is missing a street number
["Palais de l'Élysée"] is wrong
It’s okay to not provide all of the items:
[10, "Downing", "Street"] is ok
And, by default, it’s also okay to add additional items to end:
[1600, "Pennsylvania", "Avenue", "NW", "Washington"] is ok
item具有的属性是:
- additionalItems :该additionalItems关键字控制是否有效有超出了所定义的数组中的其他项目items。在这里,我们将重用上面的示例模式,但设置 additionalItems为false,这会导致不允许数组中的额外项。
- minItems、maxItems:minItems和 maxItems关键字指定数组的长度。每个关键字的值必须是非负数。
- Uniqueness:模式可以确保数组中的每个项都是唯一的。只需将uniqueItems关键字设置为true。
{ "type": "boolean" }
OK:
true
false
wrong:
"true"
0
布尔类型只匹配两个特殊值:true和 false。请注意,架构不接受评估为true或的值false,例如1和0
{ "type": "null" }
ok:
null
wrong:
false
0
""
null类型通常用于表示缺失值。当模式指定a type时null,它只有一个可接受的值:null
USERS_SCHEMA = {
"type": "object",
"required": ["users"],
"properties": {
"users": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "email"],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 30,
},
"primary_sector": {
"type": "string",
"maxLength": 60,
},
"second_sector": {
"type": "string",
"maxLength": 60,
},
"tertiary_sector": {
"type": "string",
"maxLength": 60,
},
"email": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"pattern": '^([a-zA-Z0-9]+[-_.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[-_.]?)*'\
'[a-zA-Z0-9]+\.[a-zA-Z]{2,6}$',
}
},
},
},
},
}
用来对应的符合要求的json是
{
"users":{
[{
"name": "hello",
"primary_sector": "一级部门",
"second_sector": "二级部门",
"tertiary_sector": "三级部门",
"email" : "邮箱",
}],
[{
"name": "hello1",
"primary_sector": "一级部门",
"second_sector": "二级部门",
"tertiary_sector": "三级部门",
"email" : "邮箱",
}],
}
}
可以一次性验证json里含有多有输入用户资料的json,也可以验证一个或者多个user。
Json Schema给人感觉比较像在写json正则表达式,按着基本的帮助文档和知道,通过组合基本就能写出你需要的json验证格式,然后验证的时候只需要一句validate()就可以了,如果验证失败会抛出异常。建议以后验证json格式还是习惯使用这种验证方式,会大大提高开发效率。
上面是我的一些个人理解和看法,如果有错误,请多指教。
原文地址:https://blog.csdn.net/aizenggege/article/details/82709790
https://json-schema.org/understanding-json-schema/reference/null.html
http://imweb.io/topic/56b1b4bb5c49f9d377ed8ee9
http://taobaofed.org/blog/2016/01/25/jsonschema/
https://cloud.tencent.com/developer/article/1005810