[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