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 模式日期时间检查不正确的主要内容,如果未能解决你的问题,请参考以下文章

struts2 json 输出日期格式不正确

如何结合两个 UIDatePickers 的日期和时间?

如何正确地将数据帧的所有日期时间列转换为 iso 格式

如何在 TSQL 函数中检查正确的日期时间格式?

使用Jackson时转换JSON时,日期格式设置

我无法正确生成能够兑换 JSON 日期的 kotlin 对象