python-jsonschema / jsonschema

An implementation of the JSON Schema specification for Python
https://python-jsonschema.readthedocs.io
MIT License
4.52k stars 574 forks source link

`"format":"date-time"` not working #1229

Closed JakeSummers closed 4 months ago

JakeSummers commented 4 months ago

TLDR

String formatting isn't working. I have installed the format extras. :)

Environment Info

$ python --version
Python 3.10.12

$ poetry --version
Poetry (version 1.5.1)

$ poetry show jsonschema --tree
jsonschema 4.21.1 An implementation of JSON Schema validation for Python
├── attrs >=22.2.0
├── fqdn *
├── idna *
├── isoduration *
│   └── arrow >=0.15.0
│       ├── python-dateutil >=2.7.0
│       │   └── six >=1.5
│       └── types-python-dateutil >=2.8.10
├── jsonpointer >1.13
├── jsonschema-specifications >=2023.03.6
│   └── referencing >=0.31.0
│       ├── attrs >=22.2.0
│       └── rpds-py >=0.7.0
├── referencing >=0.28.4
│   ├── attrs >=22.2.0
│   └── rpds-py >=0.7.0
├── rfc3339-validator *
│   └── six *
├── rfc3987 *
├── rpds-py >=0.7.1
├── uri-template *
└── webcolors >=1.11

Test Case

import json
import pytest
from jsonschema import validate
from jsonschema.exceptions import ValidationError

def test_date_format():
    schema = json.loads("""
    {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
            "aDate": {
                "type": "string",
                "format": "date-time"
            }
        }
    }
    """)
    example = json.loads("""
    {
        "aDate": "not a date"
    }
    """)

    with pytest.raises(ValidationError):
        validate(example, schema)

Returns:

test_schemas.py:62 (test_date_format)
def test_date_format():
        schema = json.loads("""
        {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
                "aDate": {
                    "type": "string",
                    "format": "date-time"
                }
            }
        }
        """)
        example = json.loads("""
        {
            "aDate": "not a date"
        }
        """)

>       with pytest.raises(ValidationError):
E       Failed: DID NOT RAISE <class 'jsonschema.exceptions.ValidationError'>

test_schemas.py:82: Failed
Julian commented 4 months ago

https://python-jsonschema.readthedocs.io/en/stable/faq/#my-schema-specifies-format-validation-why-do-invalid-instances-seem-valid

JakeSummers commented 4 months ago

Thanks for the link @Julian . Follow up question for you.

The doc you linked only discusses Draft 2019-09 and below. It looks like json-schema 2020-12 introduced a new term: format-assertion:

image

Link

image

Link

Is it correct that you do not currently support format-assertion?

Julian commented 4 months ago

Supporting it via what mechanism?

JakeSummers commented 4 months ago

Supporting it via what mechanism?

Any mechanism 😄 .

I would like to validate that the data inside my strings is correctly formatted as a date-time.

Julian commented 4 months ago

I literally linked you to the docs to do so :)

JakeSummers commented 4 months ago

Thanks, I see it now.

The solution is hidden in the See also box here:

image

For anyone else running into the same issue, the fix is pretty simple:

@@ -3,6 +3,7 @@ import json
 import pytest
 from jsonschema import validate
 from jsonschema.exceptions import ValidationError
+from jsonschema.validators import Draft202012Validator

 @pytest.mark.parametrize(
@@ -79,4 +80,7 @@ def test_date_format():
     """)

     with pytest.raises(ValidationError):
-        validate(example, schema)
+        validate(example,
+                 schema,
+                 format_checker=Draft202012Validator.FORMAT_CHECKER,
+                 )

Link to doc on solution: https://python-jsonschema.readthedocs.io/en/stable/validate/#validating-formats