[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
Sun Mar 22 21:44:44 UTC 2026
#64926: REST API: GET requests fail object/array schema validation when params are
JSON-serialized strings
-------------------------------------------------+-------------------------
Reporter: dsmy | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting
| Review
Component: REST API | Version: trunk
Severity: normal | Keywords: needs-patch
Focuses: javascript, rest-api, php- |
compatibility |
-------------------------------------------------+-------------------------
== The problem
When a REST endpoint declares a parameter with "type": "object" or "type":
"array", GET requests cannot pass that parameter correctly.
URLSearchParams has no native way to encode nested structures, so the only
option is JSON.stringify(), producing ?input={"post_id":123}.
PHP populates $_GET['input'] as a raw string.
rest_validate_value_from_schema() receives a string where the schema
expects object, and returns a WP_Error, the request is rejected before
rest_sanitize_value_from_schema() can coerce it.
rest_sanitize_value_from_schema() already handles this case correctly
(calls json_decode() on strings before validating type). The fix is to
apply the same coercion in rest_validate_value_from_schema(), or to add a
pre-validation JSON-decode pass for GET params that match an object/array
schema, mirroring what parse_json_params() does for application/json body
requests.
Affected file: wp-includes/rest-api.php —
rest_validate_value_from_schema()
Steps to reproduce:
Register an endpoint with a param declared as "type": "object" Call it via
GET with ?param{"key":"value"}
Receive a 400: "param is not of type object"
Workaround(see example below): Force POST method, or manually
json_decode() the param in the endpoint callback before use.
The closest historical ticket is
[#42961](https://core.trac.wordpress.org/ticket/42961) ("REST API: Cannot
pass empty object url encoded data", closed fixed in 2017) but that was
about PHP bracket-notation encoding of empty arrays, not the
`JSON.stringify` + `rest_validate_value_from_schema` ordering problem.
== Workaround
Until a core fix lands, the following filter coerces JSON-string GET
params before validation runs:
add_filter( 'rest_request_before_callbacks', function( $response,
$handler, $request ) {
if ( 'GET' !== $request->get_method() ) {
return $response;
}
foreach ( $handler['args'] ?? array() as $key => $arg_schema ) {
$type = $arg_schema['type'] ?? '';
if ( in_array( $type, array( 'object', 'array' ), true ) ) {
$value = $request->get_param( $key );
if ( is_string( $value ) ) {
$decoded = json_decode( $value, true );
if ( null !== $decoded ) {
$request->set_param( $key, $decoded );
}
}
}
}
return $response;
}, 10, 3 );
The proper fix belongs in `rest_validate_value_from_schema()` in `wp-
includes/rest-api.php`, mirroring the json_decode coercion already present
in `rest_sanitize_value_from_schema()`.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/64926>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list