[wp-trac] [WordPress Trac] #64926: REST API: GET requests fail object/array schema validation when params are JSON-serialized strings
WordPress Trac
noreply at wordpress.org
Thu Apr 2 04:48:46 UTC 2026
#64926: REST API: GET requests fail object/array schema validation when params are
JSON-serialized strings
-------------------------+-------------------------------------------------
Reporter: dsmy | Owner: (none)
Type: defect | Status: new
(bug) |
Priority: normal | Milestone: Awaiting Review
Component: REST API | Version:
Severity: normal | Resolution:
Keywords: has-patch | Focuses: javascript, rest-api, php-
| compatibility
-------------------------+-------------------------------------------------
Comment (by liaison):
Replying to [comment:21 abcd95]:
> IMO, placing the decode at the top of the function misses `anyOf/oneOf`
schemas with no top-level type, and the $type resolves to `''` and the
block is skipped on the initial call. It only works because recursive
calls from rest_find_any_matching_schema() re-enter with the sub-schema's
type set.
>
> Moving the decode inside the switch (validation) and before
rest_sanitize_array()/rest_sanitize_object() (sanitization) ensures it
fires after type resolution, regardless of schema.
Thanks @abcd95. The assessment is correct. Moving the decoding logic after
the type resolution ensures full compatibility with schemas that rely
solely on anyOf or oneOf without a top-level type declaration.
{{{#!php
<?php
function rest_sanitize_value_from_schema( $value, $args, $param = '' ) {
...
if ( 'array' === $args['type'] ) {
if ( is_string( $value ) ) {
$trimmed_value = trim( $value );
if ( str_starts_with( $trimmed_value, '[' ) ) {
$decoded = json_decode( $value, true );
if ( json_last_error() === JSON_ERROR_NONE ) {
$value = $decoded;
}
}
}
$value = rest_sanitize_array( $value );
...
}
if ( 'object' === $args['type'] ) {
if ( is_string( $value ) ) {
$trimmed_value = trim( $value );
if ( str_starts_with( $trimmed_value, '{' ) ) {
$decoded = json_decode( $value, true );
if ( json_last_error() === JSON_ERROR_NONE ) {
$value = $decoded;
}
}
}
$value = rest_sanitize_object( $value );
....
}
...
}
function rest_validate_value_from_schema( $value, $args, $param = '' ) {
...
case 'object':
if ( is_string( $value ) ) {
$trimmed_value = trim( $value );
if ( str_starts_with( $trimmed_value, '{'
) ) {
$decoded = json_decode( $value,
true );
if ( json_last_error() ===
JSON_ERROR_NONE ) {
$value = $decoded;
}
}
}
$is_valid =
rest_validate_object_value_from_schema( $value, $args, $param );
break;
case 'array':
if ( is_string( $value ) ) {
$trimmed_value = trim( $value );
if ( str_starts_with( $trimmed_value, '['
) ) {
$decoded = json_decode( $value,
true );
if ( json_last_error() ===
JSON_ERROR_NONE ) {
$value = $decoded;
}
}
}
$is_valid = rest_validate_array_value_from_schema(
$value, $args, $param );
break;
...
}
}}}
--
Ticket URL: <https://core.trac.wordpress.org/ticket/64926#comment:22>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list