jsonrainbow / json-schema

PHP implementation of JSON schema. Fork of the http://jsonschemaphpv.sourceforge.net/ project
MIT License
3.55k stars 355 forks source link

Inconsistent behavior with allOf/oneOf between master branch and latest release (v5.2.13) #702

Closed dgiotas closed 1 year ago

dgiotas commented 1 year ago

I'm working on a project that uses the library to do validation of data passed for processing. I'm experiencing a strange behavior between master branch and latest release available from composer. Using the following extract of the given schema:

JSON schema

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "type": "object",
  "required": [
    "data"
  ],
  "additionalProperties": true,
  "properties": {
    "data": {
      "type": "object",
      "required": [
        "features"
      ],
      "properties": {
        "features": {
          "type": "array",
          "items": {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "attributeId": {
                    "type": "string"
                  }
                }
              },
              {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "attributeType": {
                        "const": "date"
                      },
                      "attributeValue": {
                        "type": "string",
                        "format": "date"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "attributeType": {
                        "const": "dateTime"
                      },
                      "attributeValue": {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})Z$"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "attributeType": {
                        "const": "text"
                      },
                      "attributeValue": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            ]
          },
          "uniqueItems": true
        }
      }
    }
  }
}

I then pass the following payload for validation:

Payload

{
  "data": {
    "features": [
      {
        "attributeId": "attr.001",
        "attributeType": "text",
        "attributeValue": "This is a nice text"
      },
      {
        "attributeId": "attr.002",
        "attributeType": "date",
        "attributeValue": "2023-01-13"
      },
      {
        "attributeId": "attr.003",
        "attributeType": "dateTime",
        "attributeValue": "2023-01-13T02:03:04Z"
      }
    ]
  }
}

When I use the ./bin/validate-json with the above two files as argument and --verbose flag on, on master I get no errors:

$ ./bin/validate-json date_date-time.json date_datetime_schema.json --verbose
OK. The supplied JSON validates against the schema.

When I checkout on the tags/v5.2.13, the above run with the same files and flags, it returns the following errors:

JSON does not validate. Violations:
[data.features[1].attributeValue] Does not match the regex pattern ^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})Z$
[data.features[1].attributeValue] Invalid date-time "2023-01-13", expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm
[data.features[1]] Failed to match exactly one schema
[data.features[1]] Failed to match all schemas
[data.features[2].attributeValue] Invalid date "2023-01-13T02:03:04Z", expected format YYYY-MM-DD
[data.features[2]] Failed to match exactly one schema
[data.features[2]] Failed to match all schemas

Additional info

I have tested on 2 environments. The PHP versions used are:

erayd commented 1 year ago

This behaviour is correct. The master branch is for v6, which adds support for draft-06 of the spec. There are no current releases of this branch, although bugfixes which do not break backwards compatibility are backported to the 5.x.x branch. The 5.x.x release branch does not support draft-06 (it is draft-03/draft-04 only).

Because the const constraint was only introduced in draft-06, v5.x.x correctly ignores it during validation. This means that your data is considered to match more than one branch of the oneOf, thereby failing validation.

The v6/master branch is honestly the more robust one at this stage, so feel free to go ahead and use that one.

dgiotas commented 1 year ago

Thank you for the clarification. The bad thing is that we cannot use the v6/master branch due to a conflict with another package (codeception/module-rest). Is there a plan for an official release for v6?

erayd commented 1 year ago

Is there a plan for an official release for v6?

Yes, but there has been such a plan for many years. The problem is that it isn't finished, and nobody has any time to finish it. It's pretty close though, so if someone wanted to pick up the effort to get it shipped, that would help.

The bad thing is that we cannot use the v6/master branch due to a conflict with another package (codeception/module-rest).

What specifically is causing the conflict? A v6 release seems unlikely to resolve it, as v6 is the master branch, and introduces notable behavioural changes (the const example above being one such) - that is why it's a separate major version in the first place. However, in many cases, the differences in behaviour aren't actually an issue for the intended use-case, and v6 can simply be used instead of 5.x.x without issue.

dgiotas commented 1 year ago

What specifically is causing the conflict?

The codeception/module-rest package requires a ~5.2.3 version of the this package. I know we can tweak composer.json file using something similar to "justinrainbow/json-schema": "master as 5.2.x-dev" to resolve it, but is it not accepted by the team.

erayd commented 1 year ago

Would defining master as something like v6.0.0-beta be an acceptable workaround for you? Or do you need an actual release on this repo?

dgiotas commented 1 year ago

It seems that it doesn't depend on me. I can see that codecept/module-rest has minimum-stability set to RC. So even a beta will not be OK. Anyhow, there is no need to rush things. We will revisit the part where this is needed on later stage.

Thank you a lot for the information.