json架构日期时间未正确检查

时间:2013-11-28 10:54:31

标签: json datetime jsonschema

我有一个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”,则架构不会再注意到它不是日期时间。

我是否遗漏了架构中的任何内容?

6 个答案:

答案 0 :(得分:29)

对于Python的jsonschema库,请在调用validate时指定格式检查器:

jsonschema.validate(data, schema, format_checker=jsonschema.FormatChecker())

要验证日期时间格式,应安装strict-rfc3339包。

请参阅Validating Formats

答案 1 :(得分:9)

使用"format"进行验证是可选的。这部分是因为允许模式作者完全构成新格式,因此期望验证所有格式是不合理的。

您的库(如果它是正确的)有办法为特定格式注册自定义验证器。例如,tv4验证库(在JavaScript中)具有tv4.addFormat() method

tv4.addFormat('date-time', function (data) {
    return isValidDate(data);
});

完成此操作后,架构中的"format": "date-time"应正确验证日期。

答案 2 :(得分:4)

您正在使用的JSON模式验证的实现很可能需要日期和时间组件之间的T分隔符。这是它所基于的RFC3339规范和ISO8601的主要内容。虽然两者都有省略T的规定,但它们都可以通过协议来实现,而不是强制要求支持。 (去图。)

此外,RFC3339 要求您包含时区偏移量或Z以指示UTC。这将其锁定到特定时刻,而不是在某个未知时区中人为代表。由于您既不需要,也可能验证失败。

来自JSON Schema spec

  

<强> 7.3.1.2。验证

     

如果字符串实例是 RFC 3339,第5.6节 [RFC3339]定义的有效日期表示,则该字符串实例对此属性有效。

答案 3 :(得分:2)

我使用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;
}

答案 4 :(得分:0)

在此示例中,如果将"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"]
}

答案 5 :(得分:-1)

您可以更改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