WordPress 5.5 introduces a number of new features and changes to how request and response parameters are handled, particularly around JSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. Schema features.
General
Support more JSON Schemas when filtering a response by context
The REST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. uses context
to remove fields from a response if the user does not have adequate permissions or for performance reasons. For example, in the following schema, if the user requested the resource with context=view
, only the name
properties would be returned.
{
"type": "object",
"properties": {
"name": {
"type": "string",
"context": [ "view", "edit" ]
},
"role": {
"type": "string",
"context": [ "edit" ]
}
}
}
In [47758], support was added for removing more properties from a response if additional features were in use. The array
type, multi-types, and the additionalProperties
keyword are now supported. Additionally, the filter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. recurses to an infinite depth.
So for the following schema, if the resource was requested with context=view
the following fields would be returned.
{
"type": "object",
"properties": {
"notes": {
"context": [ "view", "edit" ],
"type": "array",
"items": {
"type": "object",
"properties": {
"note": {
"context": [ "view", "edit" ],
"type": "string"
},
"ip": {
"context": [ "edit" ],
"type": "string"
}
}
}
}
}
}
Note that the ip
field has been omitted.
{
"notes": [
{
"note": "My Note"
}
]
}
For more information, see #48819 on Trac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..
Inconsistent parameter type handling in WP_REST_Request::set_param()
Previously, when parameters were manually added to a WP_REST_Request
object using set_param()
, the parameter was added into the first available parameter slot. This could be unexpected if a parameter was already in another parameter slot and you were trying to overwrite the value.
In [47559], this changed to first look for an existing parameter, and then falls back to the first parameter in the order if none was found.
For more information, refer to the relevant Trac ticket Created for both bug reports and feature development on the bug tracker. (#40838).
WP_REST_Controller::get_endpoint_args_for_item_schema
drops some keywords
The primary mechanism for developers to declare the parameters an endpoint accepts is by writing a JSON Schema in WP_REST_Controller::get_item_schema()
. The schema is then transformed into the args
format by using WP_REST_Controller::get_endpoint_args_for_item_schema()
during route registration. This transformation process dropped the minimum
, maximum
, exclusiveMinimum
, and exclusiveMaximum
JSON Schema keywords. This list of allowed keywords was updated in [47911] to ensure this doesn’t happen.
For more information, check out #50301 on Trac.
Check required properties are provided when validating an object
Previously, the REST API would validate that all parameters with the required
attribute were provided in WP_REST_Request::has_valid_params
. This meant that if an object was defined with its own set of required parameters, it was not checked by the default parameter validator.
So, for instance, given the following schema, the request would be accepted despite the missing version
field.
{
"type": "object",
"properties": {
"fixed_in": {
"required": true,
"type": "object",
"properties": {
"revision": {
"required": true,
"type": "integer"
},
"version": {
"required": true,
"type": "string"
}
}
}
}
}
{
"fixed_in": {
"revision": 47809
}
}
In [47809] this was fixed to now generate a rest_property_required
error.
Version 4 syntax
This change also adds support for JSON Schema Version 4 required-property syntax where the list of required properties for an object is defined as an array of property names. This can be particularly helpful when specifying that a meta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. value has a list of required properties.
Given the following meta field.
register_post_meta( 'post', 'fixed_in', array(
'type' => 'object',
'show_in_rest' => array(
'single' => true,
'schema' => array(
'required' => array( 'revision', 'version' ),
'type' => 'object',
'properties' => array(
'revision' => array(
'type' => 'integer',
),
'version' => array(
'type' => 'string',
),
),
),
),
) );
And the following request object.
{
"title": "Check required properties",
"content": "We should check that required properties are provided",
"meta": {
"fixed_in": {
"revision": 47089
}
}
}
The following error will be returned.
{
"code": "rest_property_required",
"message": "version is a required property of meta.fixed_in.",
"data": {
"status": 400
}
}
If the fixed_in
meta field was omitted entirely, no error would be generated. An object that defines a list of required properties does not indicate that the object itself is required to be submitted. Just that if the object is included, that the listed properties must also be included as well.
Specifying the required properties in the top-level schema for an endpoint using a required
array is not supported. Given the following schema, a user could successfully submit a request without the title
or content
properties. This is because, as discussed earlier, the schema document is not itself used for validation, but instead transformed to a list of parameter definitions.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "my-endpoint",
"type": "object",
"required": [ "title", "content" ],
"properties": {
"title": {
"type": "string"
},
"content": {
"type": "string"
}
}
}
For more information, refer to #48818 on Trac.
Make multi-typed schemas more robust
A multi-type schema is a schema where the type
keyword is an array of possible types instead of a single type. For instance, [ 'object', 'string' ]
would allow objects or string values.
In [46249] basic support for these schemas was introduced. The validator would loop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. over each schema type trying to find a version that matched. This worked for valid values, but for invalid A resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. values it provided unhelpful error messages. The sanitizer also had its utility restricted.
In [48306], the validators and sanitizers will now first determine the best type of the passed value and then apply the schema with that set type. In the case that a value could match multiple types, the schema of the first matching type will be used.
So, for instance, given the following schema, if the value 40
was submitted for the parameter, the user would receive param must be between 10 (inclusive) and 20 (inclusive)
as an error message instead of param is not of type null,integer
.
{
"type": [ "null", "integer" ],
"minimum": 10,
"maximum": 20
}
Correct rest_sanitize_value_from_schema
return type
The return type of rest_sanitize_value_from_schema
has been corrected in [48307] to be mixed|WP_Error
. Previously, the function had been documented as returning true|WP_Error
.
Though WP_Error
was a documented return type, it would not have been returned before WordPress 5.5. The function now returns a WP_Error
if the value cannot be safely sanitized. For instance when checking the uniqueItems
keyword.
New Keywords
WordPress 5.5 adds support for a number of JSON Schema keywords.
Pattern
The JSON Schema keyword pattern
can be used to validate that a string
field matches a regular expression.
For instance, given the following schema, #123
would be valid, but #abc
would not.
{
"type": "string",
"pattern": "#[0-9]+"
}
The regex is not automatically anchored. Regex flags, for instance /i
to make the match case insensitive are not supported. Developers are advised to use a constrained set of regex features so the schema can be interoperable between JavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. and PHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher. The pattern should be valid according to the ECMA 262 regex dialect.
Relevant changeset: [47810].
Min and max string length
The minLength
and maxLength
keywords can be used to constrain the acceptable length of a string. Importantly multi-byte characters are counted as a single character and bounds are inclusive.
For instance, given the following schema, ab
, abc
, and abcd
are valid, while a
, and abcde
are invalid.
{
"type": "string",
"minLength": 2,
"maxLength": 4
}
The exclusiveMinimum
and exclusiveMaximum
keywords do not apply, they are only valid for numbers.
Relevant changeset: [47627].
Min and max array items
The minItems
and maxItems
keywords can be used to constrain the acceptable number of items included in an array.
For instance, given the following schema, [ 'a' ]
and [ 'a', 'b' ]
are valid, while []
and [ 'a', 'b', 'c' ]
are invalid.
{
"type": "array",
"minItems": 1,
"maxItems": 2,
"items": {
"type": "string"
}
}
Again, the exclusiveMinimum
and exclusiveMaximum
keywords do not apply.
Relevante changeset: [47923].
Unique items
The uniqueItems
keyword can be used to require that all items in an array are unique.
For instance, given the following schema, [ 'a', 'b' ]
is valid, while [ 'a', 'a' ]
is not.
{
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
}
}
Uniqueness
Items of different types are considered unique, for instance, '1'
, 1
and 1.0
are different values.
When arrays are compared, the order of items matters. So the given array is considered to have all unique items.
[
[ "a", "b" ],
[ "b", "a" ]
]
When objects are compared, the order the members appear in does not matter. So the given array is considered to have duplicate items since the values are the same, they just appear in a different order.
[
{
"a": 1,
"b": 2
},
{
"b": 2,
"a": 1
}
]
Uniqueness is checked in both rest_validate_value_from_schema
and rest_sanitize_value_from_schema
. This is to prevent instances where items would be considered unique before sanitization is applied, but after sanitization the items would converge to identical values.
Take for instance the following schema:
{
"type": "array",
"uniqueItems": true,
"items": {
"type": "string",
"format": "uri"
}
}
A request with [ "https://example.org/hello world", "https://example.org/hello%20world" ]
would pass validation because the each string value is different. However, after esc_url_raw
converted the space in the first url to %20
the values would be identical.
In this case rest_sanitize_value_from_schema
would return an error. As such, developers are advised to always validate and sanitize parameters.
For more information, see #48821 on Trac.
Format Changes
A couple of changes have been made to handling of the format
keyword.
Only validate the format keyword if the type is a string
Previously, implementing multi-type fields that had a format
keyword required disabling the default validate & sanitize callbacks. After [48300] this can now be expressed entirely in JSON Schema.
For instance, given the following schema, a user can now submit both https://example.org/hello world
and { "link": "https://example.org/hello world" }
and validation & sanitization will be properly applied in both cases.
{
"type": [ "string", "object" ],
"properties": {
"link": {
"type": "string",
"format": "uri"
},
"label": {
"type": "string"
}
},
"format": "uri"
}
For backward compatibility with invalid schemas the format
validation will still apply if the type
is not specified, or it is invalid.
Miscellaneous changes
- The
hex-color
format has been introduced. This enforces a 3
or 6
hex digit color with a leading (see #49270). - The
uuid
format has been introduced. This enforces a uuid
of any version using the wp_is_uuid
function (see #50053). - The
rest_validate_value_from_schema
and rest_sanitize_value_from_schema
functions will now issue _doing_it_wrong
notices if the type
keyword is missing or contains invalid values. The following types are valid: object
, array
, string
, number
, integer
, boolean
, and null
(see #48821). - The following functions have been introduced to encapsulate type validation & sanitization:
rest_is_integer
, rest_is_array
, rest_sanitize_array
, rest_is_object
and rest_sanitize_object
(see #48821).
Props @desrosj, @davidbaumwald, and @justinahinon for reviewing.
#5-5, #dev-notes, #rest-api