json 模式日期时间检查不正确
Posted
技术标签:
【中文标题】json 模式日期时间检查不正确【英文标题】:json schema date-time does not check correctly 【发布时间】:2013-12-14 08:59:12 【问题描述】:我有一个 JSON 和一个 JSON 模式
JSON:
"aaa": "4000-02-01 00:00:00"
JSON 模式:
"$schema": "http://json-schema.org/draft-04/schema",
"type": "object",
"properties":
"aaa":
"type": "string",
"format": "date-time"
, "required": ["aaa"]
JSON 由 JSON 模式验证。但是,如果我将字段 aaa
更改为“bla”,则架构不会注意到它不再是日期时间。
我错过了架构中的任何内容吗?
【问题讨论】:
您使用什么software 来处理验证?因为有些软件有问题或者没有实现所有东西.. 甚至规范(草案 04)也说应该实现日期时间格式:json-schema.org/latest/json-schema-validation.html#anchor106 一些包可选地实现格式验证。 tv4 for nodejs 允许您通过函数调用为格式添加验证。也许其他图书馆至少有这个功能? 【参考方案1】:我找到了使用this library 的解决方法。它检查 javascript 代码中字段的内容:
function isValidDate(datestring)
var format = d3.time.format("%Y-%m-%d %H:%M:%S");
var date = format.parse(datestring);
if (date)
return true;
return false;
【讨论】:
这很奇怪,因为它应该没有时区偏移量?【参考方案2】:"format"
的验证是可选的。这部分是因为允许架构作者完全构建新格式,因此期望所有格式都经过验证是不合理的。
您的库应该(如果合适的话)有办法为特定格式注册自定义验证器。例如,tv4
验证库(在 JavaScript 中)具有 tv4.addFormat()
method:
tv4.addFormat('date-time', function (data)
return isValidDate(data);
);
完成此操作后,架构中的 "format": "date-time"
应正确验证日期。
【讨论】:
嗯..根据specification格式和日期时间格式实现是不是可选的..它们应该被实现..关于tv4,可能是oversight? 在你链接的地方,它首先说“实现可能支持“格式”关键字。如果他们选择这样做......”。因此,完全支持“格式”是可能的——但如果你这样做了,那么你应该支持标准集。 开箱即用,tv4 根本不支持任何“格式”值。但是,该项目肯定在寻找一组标准的“格式”验证器,因此如果您愿意,可以提供帮助。 :) 是的,但您同意 tv4 绝对支持格式关键字,因此:“they SHOULD implement validation for attributes defined below”(日期时间)。是的 tv4 文档说“There are no built-in format validators”。我将制作自己的验证器,并可能将它们提交给 tv4 项目:) +1 用于为标准集编写/提交一组验证器。【参考方案3】:您正在使用的 JSON 模式验证的实现很可能需要在日期和时间组件之间使用 T
分隔符。这是它所基于的RFC3339 规范和ISO8601 的主要内容。虽然两者都有省略T
的规定,但它们都使它成为可以通过协议完成的事情,而不是强制支持的事情。 (上图。)
此外,RFC3339 确实要求您包含时区偏移或 Z
以指示 UTC。这会将其锁定在特定的时间点,而不是某个未知时区的人类代表。由于您都没有要求,因此很可能验证失败。
来自JSON Schema spec:
7.3.1.2。验证
如果字符串实例是由 RFC 3339, section 5.6 [RFC3339] 定义的有效日期表示,则该字符串实例对该属性有效。
【讨论】:
【参考方案4】:对于Python的jsonschema库,调用validate
时指定格式检查器:
jsonschema.validate(data, schema, format_checker=jsonschema.FormatChecker())
要验证日期时间格式,应安装 strict-rfc3339 包。
见Validating Formats。
【讨论】:
谢谢!因为我是一个 Python 新手,所以我意识到你可以pip install strict-rfc3339
花费的时间比它应该的要长。无论如何,就像一个魅力!
有没有办法将format_checker
参数与iter_errors
一起使用?
@CMCDragonkai 当您实例化验证器时,您应该能够使用format_checker
。例如:validator = jsonschema.Draft7Validator(schema, format_checker=jsonschema.FormatChecker()); validator.iter_errors(document)
.【参考方案5】:
您可以更改 python jsonschema 模块的源代码。
在jsonschema/_format.py
func is_date_time(instance)
找到与日期时间相关的代码。像这样,关于 2.6.0 版的第 204 - 225 行:
try:
import strict_rfc3339
except ImportError:
try:
import isodate
except ImportError:
pass
else:
@_checks_drafts("date-time", raises=(ValueError, isodate.ISO8601Error))
def is_datetime(instance):
if not isinstance(instance, str_types):
return True
return isodate.parse_datetime(instance)
else:
@_checks_drafts("date-time")
def is_datetime(instance):
if not isinstance(instance, str_types):
return True
return strict_rfc3339.validate_rfc3339(instance)
注释掉上面的内容并粘贴,或者将上面的_check_drafts
函数替换为:
@_checks_drafts("date-time")
def is_datetime(instance):
if not isinstance(instance, str_types):
return True
try:
datetime.datetime.strptime(instance, "%Y-%m-%d %H:%M:%S")
except ValueError:
return False
return True
【讨论】:
请告诉我在哪里,我找不到。谢谢~~ @CodeCaster 不,他们有英文翻译,下面是中文翻译。【参考方案6】:在此示例中,如果您将 "aaa"
更改为 "bla"
,您将添加一个未定义的新属性,因此架构将仅验证 "aaa"
。如果您不想添加属性,我相信您应该添加"additionalProperties": false
。示例如下:
这里的架构声明 "aaa"
是唯一的属性,它的值应该是日期时间。
"$schema": "http://json-schema.org/draft-04/schema",
"type": "object",
"additionalProperties": false,
"properties":
"aaa":
"type": "string",
"format": "date-time"
, "required": ["aaa"]
【讨论】:
以上是关于json 模式日期时间检查不正确的主要内容,如果未能解决你的问题,请参考以下文章