[PHP-DEV] [RFC] JSON Schema validation support

Hello,

I would like introduce and open discussion for RFC proposing the addition of JSON Schema validation support to JSON extension:

https://wiki.php.net/rfc/json_schema_validation

If this is successful, it should be just the first for further improvements (see the future scope).

Kind regards,

Jakub

Hi, Jakub!

I like the idea. I have a couple of initial thoughts:

  1. Wouldn’t it make sense to place all the new classes under the Json namespace, similar to how it’s done in ext-random?
  2. If there’s no way to interact with the JsonSchema class, what purpose does it serve? Wouldn’t it be simpler to just extend json_decode() with an optional ?string $schema = null parameter?
···

Kind regards,
Valentin

Hi,

On Fri, Jul 4, 2025 at 11:49 PM Valentin Udaltsov <udaltsov.valentin@gmail.com> wrote:

On Sta, 5 July 2025 at 00:04, Jakub Zelenka <bukka@php.net> wrote:

Hello,

I would like introduce and open discussion for RFC proposing the addition of JSON Schema validation support to JSON extension:

https://wiki.php.net/rfc/json_schema_validation

If this is successful, it should be just the first for further improvements (see the future scope).

Kind regards,

Jakub

Hi, Jakub!

I like the idea. I have a couple of initial thoughts:

  1. Wouldn’t it make sense to place all the new classes under the Json namespace, similar to how it’s done in ext-random?

This would be widely inconsistent with the current interface / exception class in the extension. The ext-random was a new extension so it’s a completely different case. I think it makes much more sense to keep the extension consistent than introducing new interface.

  1. If there’s no way to interact with the JsonSchema class, what purpose does it serve? Wouldn’t it be simpler to just extend json_decode() with an optional ?string $schema = null parameter?

There are couple of reasons for this:

  • It allows re-using the same parsed schema without a need to parse it multiple times for each decoding / validation - the class internally holds parsed representation of the schema.
  • We might want to introduce additional flags that will impact the parsing (e.g. default version)
  • It might allow a way to better cache schema between requests so it could further improve performance in the future
  • It will allow the possibility to get schema from other sources than string - e.g. from PHP array or even automatic creation from the class (that’s why the JsonSchema is created using static method and not using constructor). This might be especially useful for object mapping.

Kind regards,

Jakub

On Jul 4, 2025, at 16:01, Jakub Zelenka <bukka@php.net> wrote:

Hello,

I would like introduce and open discussion for RFC proposing the addition of JSON Schema validation support to JSON extension:

PHP: rfc:json_schema_validation

If this is successful, it should be just the first for further improvements (see the future scope).

Kind regards,

Jakub

There are 9 versions of JSON Schema and 11 Internet-Drafts, all of which have expired. Many of these versions are still widely used in the wild (draft-04, draft-05, and draft-06 come to mind as heavily used, despite several newer versions).

Which version do you plan to target with this RFC, or will it be able to parse all versions, depending on what the input has specified in the `$schema` properties? I’ve even seen multiple schema versions used within the same set of referenced documents, and as long as the parser knows how to handle all versions, it will parse things just fine.

For the reference of others on the list, here’s what I mean by 9 versions and 11 I-Ds:

* Version: 2020-12
  - draft-bhutton-json-schema-01
  - draft-bhutton-json-schema-00

* Version: 2019-09
  - draft-handrews-json-schema-02

* Version: draft-07
  - draft-handrews-json-schema-01
  - draft-handrews-json-schema-00

* Version: draft-06
  - draft-wright-json-schema-01

* Version: draft-05
  - draft-wright-json-schema-00

* Version: draft-04
  - draft-zyp-json-schema-04

* Version: draft-03
  - draft-zyp-json-schema-03

* Version: draft-02
  - draft-zyp-json-schema-02

* Version: draft-01
  - draft-zyp-json-schema-01

Typically, when you create a JSON Schema document, you specify the `$schema` property, the value of which is a URI that refers to the schema version you’re using, like this:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

This lets the parser know what “flavor” of JSON Schema you’re using. The problem is that many parsers don’t understand all schema versions, and the most popular one in PHP (justinrainbow/json-schema <https://packagist.org/packages/justinrainbow/json-schema&gt;\) only supports draft-03 and draft-04, both well over 12 years old, at this point.

Perhaps the JSON Schema library that is most robust and supports the latest versions is the opis/json-schema package <https://opis.io/json-schema/2.x/&gt;\. It supports draft-06, draft-07, 2019-09, and 2020-12, which is pretty much all the newer ones that justinrainbow/json-schema doesn’t support.

I think your RFC needs to address all these versions and how you plan to address compatibility issues between them all.

Since all the I-Ds have expired without a formal IETF RFC being voted on and passing, you should probably call attention to the fact that JSON Schema, while not moving much right now, is still a moving target and any new versions will require updates to the core to support them.

Cheers,
Ben

On Jul 4, 2025, at 18:07, Ben Ramsey <ramsey@php.net> wrote:

On Jul 4, 2025, at 16:01, Jakub Zelenka <bukka@php.net> wrote:

Hello,

I would like introduce and open discussion for RFC proposing the addition of JSON Schema validation support to JSON extension:

PHP: rfc:json_schema_validation

If this is successful, it should be just the first for further improvements (see the future scope).

Kind regards,

Jakub

There are 9 versions of JSON Schema and 11 Internet-Drafts, all of which have expired. Many of these versions are still widely used in the wild (draft-04, draft-05, and draft-06 come to mind as heavily used, despite several newer versions).

Which version do you plan to target with this RFC, or will it be able to parse all versions, depending on what the input has specified in the `$schema` properties? I’ve even seen multiple schema versions used within the same set of referenced documents, and as long as the parser knows how to handle all versions, it will parse things just fine.

For the reference of others on the list, here’s what I mean by 9 versions and 11 I-Ds:

* Version: 2020-12
- draft-bhutton-json-schema-01
- draft-bhutton-json-schema-00

* Version: 2019-09
- draft-handrews-json-schema-02

* Version: draft-07
- draft-handrews-json-schema-01
- draft-handrews-json-schema-00

* Version: draft-06
- draft-wright-json-schema-01

* Version: draft-05
- draft-wright-json-schema-00

* Version: draft-04
- draft-zyp-json-schema-04

* Version: draft-03
- draft-zyp-json-schema-03

* Version: draft-02
- draft-zyp-json-schema-02

* Version: draft-01
- draft-zyp-json-schema-01

Typically, when you create a JSON Schema document, you specify the `$schema` property, the value of which is a URI that refers to the schema version you’re using, like this:

{
 "$schema": "https://json-schema.org/draft/2020-12/schema"
}

This lets the parser know what “flavor” of JSON Schema you’re using. The problem is that many parsers don’t understand all schema versions, and the most popular one in PHP (justinrainbow/json-schema <https://packagist.org/packages/justinrainbow/json-schema&gt;\) only supports draft-03 and draft-04, both well over 12 years old, at this point.

Perhaps the JSON Schema library that is most robust and supports the latest versions is the opis/json-schema package <https://opis.io/json-schema/2.x/&gt;\. It supports draft-06, draft-07, 2019-09, and 2020-12, which is pretty much all the newer ones that justinrainbow/json-schema doesn’t support.

I think your RFC needs to address all these versions and how you plan to address compatibility issues between them all.

Since all the I-Ds have expired without a formal IETF RFC being voted on and passing, you should probably call attention to the fact that JSON Schema, while not moving much right now, is still a moving target and any new versions will require updates to the core to support them.

Cheers,
Ben

Another thing that needs to be addressed in the RFC is how error reporting will work. I see this hinted at under Future Scope, but one of the benefits of the existing JSON Schema Composer packages is the robust level of error reporting they provide.

I think robust error reporting is base-level functionality and non-optional for a minimum viable feature. I won’t have a reason to use the built-in JSON Schema functionality until it has a certain level of error reporting that goes well beyond simple `JSON_ERROR_SCHEMA_*` error codes.

I see that the JSO C library supports JSON Schema validation for draft-04 and draft-06. IMO, you will need at least 2020-12 support, since this is the version that OpenAPI 3 has adopted, and any tooling for it will require support for parsing 2020-12 schemas.

Cheers,
Ben

Hi

On Sat, Jul 5, 2025 at 1:10 AM Ben Ramsey <ramsey@php.net> wrote:

There are 9 versions of JSON Schema and 11 Internet-Drafts, all of which have expired. Many of these versions are still widely used in the wild (draft-04, draft-05, and draft-06 come to mind as heavily used, despite several newer versions).

Which version do you plan to target with this RFC, or will it be able to parse all versions, depending on what the input has specified in the $schema properties?

This is noted in the implementation section:

The current status is almost complete draft 4 and 6 support. Draft 7 support is coming soon.

By almost I mean that it needs to implement dependencies (which I plan to sort out before this goes to vote) and it didn’t go through complete regression pack which should happen before the first RC. Draft 7 is pretty much just “if” so it should be supported as well as it’s pretty similar to dependencies. I will see about other drafts if they could make it to 8.5 but the plan to support eventually all. I will make it a bit clearer in the RFC. Technically this is more library implementation thing but as it’s bundled it should be properly noted in the RFC as well.

I think your RFC needs to address all these versions and how you plan to address compatibility issues between them all.

All drafts except 4 require $schema to be there so it’s the way how to currently select the version. The future scope actually lists the default draft for schemas without $schema so it could be selected by users. We could maybe look into some auto-identification in the future but again it would be the future scope. I will add some note about it to the RFC.

Since all the I-Ds have expired without a formal IETF RFC being voted on and passing, you should probably call attention to the fact that JSON Schema, while not moving much right now, is still a moving target and any new versions will require updates to the core to support them.

Yeah good point I should mention that new version will be treated as features.

Cheers

Jakub

On Sat, Jul 5, 2025 at 1:29 AM Ben Ramsey <ramsey@php.net> wrote:

Another thing that needs to be addressed in the RFC is how error reporting will work. I see this hinted at under Future Scope, but one of the benefits of the existing JSON Schema Composer packages is the robust level of error reporting they provide.

The error reporting is done using normal error codes and exceptions get some sort of identification message. It doesn’t collect multiple errors with exact pointers to the place in the same way as the current JSON parser doesn’t do that - this is just how things are in the JSON extension and this doesn’t try to address all problems in one go - it basically needs some extra parser context for this which is not there yet.

I think robust error reporting is base-level functionality and non-optional for a minimum viable feature. I won’t have a reason to use the built-in JSON Schema functionality until it has a certain level of error reporting that goes well beyond simple JSON_ERROR_SCHEMA_* error codes.

Well you don’t have to use it from the start. The reason for introduction in this form is to mainly get something that we can build on. It is also important to know that it makes sense to spend more time on it. It already required lots of time to implement.

If we used the same standard on the json parser, we would never have json extension in PHP because the error reporting does not provide complete info.

I see that the JSO C library supports JSON Schema validation for draft-04 and draft-06. IMO, you will need at least 2020-12 support, since this is the version that OpenAPI 3 has adopted, and any tooling for it will require support for parsing 2020-12 schemas.

None of the implementations started with support for all drafts from the start. We will eventually support all but I don’t see why that would have to be done from the beginning.

Kind regards,

Jakub

On Sat, Jul 5, 2025 at 1:41 AM Jakub Zelenka <bukka@php.net> wrote:

On Sat, Jul 5, 2025 at 1:29 AM Ben Ramsey <ramsey@php.net> wrote:

Another thing that needs to be addressed in the RFC is how error reporting will work. I see this hinted at under Future Scope, but one of the benefits of the existing JSON Schema Composer packages is the robust level of error reporting they provide.

The error reporting is done using normal error codes and exceptions get some sort of identification message.

I should probably show some example how this looks like. See this test https://github.com/bukka/php-jsond/blob/1f640becf3cd0f0cca9c72fa5045c7ccefc26d7f/tests/jsond_decode_schema_002.phpt

Kind regards,

Jakub