43

I have a JSON and a JSON-schema

JSON:

{
"aaa": "4000-02-01 00:00:00"
}

JSON-schema:

{
    "$schema": "http://json-schema.org/draft-04/schema",
    "type": "object",
    "properties": {

        "aaa": {
            "type": "string",
            "format": "date-time"
        }


    }, "required": ["aaa"]
}

The JSON gets validated by the JSON-schema. However if I change the field aaa to "bla" the schema does not notice that it is not a date-time any longer.

Did I miss anything in the schema?

JoachimR
  • 5,150
  • 7
  • 45
  • 50
  • What [software](http://json-schema.org/implementations.html) are you using to process the validation? Because some software are buggy or do not implements everything.. even the specification (draft 04) says that date-time format SHOULD be implemented: http://json-schema.org/latest/json-schema-validation.html#anchor106 – Yves M. Jan 14 '14 at 11:35
  • Some packages optionally implement format validation. tv4 for nodejs lets you add validations for the formats via a function call. Maybe other libraries at least have this feature? – EthernetCable Apr 26 '14 at 19:37

6 Answers6

52

For Python's jsonschema library, specify the format checker when calling validate:

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

To validate a date-time format, the strict-rfc3339 package should be installed.

See Validating Formats.

bcb
  • 1,977
  • 2
  • 22
  • 21
  • 1
    Thanks! Because I am a Python newbie it took longer than it should for me to realise you can `pip install strict-rfc3339`. Anyway, works like a charm! – Darragh Enright Jun 21 '15 at 13:42
  • Is there a way to use `format_checker` argument with `iter_errors`? – CMCDragonkai Sep 21 '20 at 03:59
  • 1
    @CMCDragonkai You should be able to use `format_checker` when you instantiate the validator. For example: `validator = jsonschema.Draft7Validator(schema, format_checker=jsonschema.FormatChecker()); validator.iter_errors(document)`. – Tim Ludwinski Nov 18 '20 at 21:52
9

Validation with "format" is optional. This is partly because schema authors are allowed to completely make up new formats, so expecting all formats to be validated is not reasonable.

Your library should (if it is decent) have a way to register custom validators for particular formats. For example, the tv4 validation library (in JavaScript) has the tv4.addFormat() method:

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

Once you've done this, then "format": "date-time" in the schema should validate dates correctly.

cloudfeet
  • 12,156
  • 1
  • 56
  • 57
  • Hum.. According to the [specification](http://json-schema.org/latest/json-schema-validation.html#anchor106) format and also **date-time format** implementation are **not optional**.. They SHOULD be implemented.. Concerning tv4, it's probably an [oversight](https://github.com/geraintluff/tv4/search?q=date-time&ref=cmdform)? – Yves M. Jan 14 '14 at 11:40
  • 2
    Right where you linked, it first says "Implementations **MAY** support the "format" keyword. Should they choose to do so...". So it's a MAY for supporting "format" at all - but if you do, then you SHOULD support the standard set. – cloudfeet Jan 15 '14 at 10:05
  • 2
    Out-of-the-box, tv4 doesn't support any "format" values at all. However, the project is definitely looking for a standard set of "format" validators, so you could help out if you like. :) – cloudfeet Jan 15 '14 at 10:08
  • Yep but you agree that tv4 definitely supports the format keyword so: "[they SHOULD implement validation for attributes defined below](http://json-schema.org/latest/json-schema-validation.html#anchor106)" (date-time). Yep tv4 documentation says that "[There are no built-in format validators](https://github.com/geraintluff/tv4#addformatformat-validationfunction)". I'm gonna make my own validators and maybe submit them to tv4 project :) – Yves M. Jan 15 '14 at 11:04
  • +1 for writing/submitting a set of validators for the standard set. – cloudfeet Jan 15 '14 at 16:27
  • @cloudfeet I tried use `addFormat` but seems not execute, always get the error `ValidationError: Invalid type: string (expected newformatname)` would you see my question http://stackoverflow.com/questions/36105527/how-to-allow-nan-as-number-with-tv4-validate, do I miss something? – user1575921 Mar 19 '16 at 22:03
8

It is highly likely that the implementation of JSON schema validation that you're using is requiring the T separator between the date and time components. This is a staple of the RFC3339 spec and ISO8601 which it is based upon. While both have provisions for omitting the T, they both make it something that can be done by agreement, rather then a mandatory thing to support. (Go figure.)

Also, RFC3339 does require that you include either a time zone offset or a Z to indicate UTC. This locks it down to a particular moment in time, rather than a human representation of one in some unknown time zone. Since you have required neither, that's likely while it has failed validation.

From the JSON Schema spec:

7.3.1.2. Validation

A string instance is valid against this attribute if it is a valid date representation as defined by RFC 3339, section 5.6 [RFC3339].

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
2

I found a workaround by using this library. It checks the content of the field in javascript code:

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;
}
JoachimR
  • 5,150
  • 7
  • 45
  • 50
0

In this example, if you change "aaa" to "bla" you are adding a new property that is not defined and hence the schema will only validate "aaa". If you do not want to add properties I believe you should add "additionalProperties": false. Example below:

Here the schema states that "aaa" is the only property and its values should be in date-time.

{
    "$schema": "http://json-schema.org/draft-04/schema",
    "type": "object",
    "additionalProperties": false,
    "properties": {

        "aaa": {
            "type": "string",
            "format": "date-time"
        }


    }, "required": ["aaa"]
}
Murali
  • 1
-2

You can change the source code for the python jsonschema module.

Find the datetime-related code, at jsonschema/_format.py func is_date_time(instance). Like this, about line 204 - 225, for version 2.6.0:

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)

Comment out the above and paste this, or replace the _check_drafts function above with this:

@_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
  • 147,647
  • 23
  • 218
  • 272