Title: REST API Parameter &amp; JSON Schema changes in WordPress 5.5
Author: Timothy Jacobs
Published: July 16, 2020

---

 [  ](https://profiles.wordpress.org/timothyblynjacobs/) [Timothy Jacobs](https://profiles.wordpress.org/timothyblynjacobs/)
8:06 pm _on_ July 16, 2020     
Tags: [5.5 ( 87 )](https://make.wordpress.org/core/tag/5-5/),
[dev-notes ( 648 )](https://make.wordpress.org/core/tag/dev-notes/), [rest-api ( 111 )](https://make.wordpress.org/core/tag/rest-api/)

# REST API Parameter & JSON Schema changes in WordPress 5.5

WordPress 5.5 introduces a number of new features and changes to how request and
response parameters are handled, particularly around JSONJSON 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 APIREST 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/](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.

    ```notranslate
    {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "context": [ "view", "edit" ]
        },
        "role": {
          "type": "string",
          "context": [ "edit" ]
        }
      }
    }
    ```

In [[47758]](https://core.trac.wordpress.org/changeset/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 filterFilter Filters are one of the two types of Hooks [https://codex.wordpress.org/Plugin_API/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.

    ```notranslate
    {
      "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.

    ```notranslate
    {
      "notes": [
        {
          "note": "My Note"
        }
      ]
    }
    ```

For more information, see [#48819](https://core.trac.wordpress.org/ticket/48819)
on TracTrac 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]](https://core.trac.wordpress.org/changeset/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 ticketticket Created for both bug
reports and feature development on the bug tracker. ([#40838](https://core.trac.wordpress.org/ticket/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]](https://core.trac.wordpress.org/changeset/47911)
to ensure this doesn’t happen.

For more information, check out [#50301](https://core.trac.wordpress.org/ticket/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.

    ```notranslate
    {
      "type": "object",
      "properties": {
        "fixed_in": {
          "required": true,
          "type": "object",
          "properties": {
            "revision": {
              "required": true,
              "type": "integer"
            },
            "version": {
              "required": true,
              "type": "string"
            }
          }
        }
      }
    }
    ```

    ```notranslate
    {
      "fixed_in": {
        "revision": 47809
      }
    }
    ```

In [[47809]](https://core.trac.wordpress.org/changeset/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 metaMeta 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.

    ```notranslate
    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.

    ```notranslate
    {
    	"title": "Check required properties",
    	"content": "We should check that required properties are provided",
    	"meta": {
    		"fixed_in": {
    			"revision": 47089
    		}
    	}
    }
    ```

The following error will be returned.

    ```notranslate
    {
      "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](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?output_format=md#47911),
the schema document is not itself used for validation, but instead transformed to
a list of parameter definitions.

    ```notranslate
    {
      "$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](https://core.trac.wordpress.org/ticket/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]](https://core.trac.wordpress.org/changeset/46249) basic support for 
these schemas was introduced. The validator would loopLoop 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](https://codex.wordpress.org/The_Loop)
over each schema type trying to find a version that matched. This worked for valid
values, but for invalidinvalid 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]](https://core.trac.wordpress.org/changeset/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`.

    ```notranslate
    {
      "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]](https://core.trac.wordpress.org/changeset/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.

    ```notranslate
    {
      "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 JavaScriptJavaScript
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](https://www.javascript.com/)
and PHPPHP 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](https://www.ecma-international.org/ecma-262/5.1/#sec-15.10.1).

Relevant changeset: [[47810]](https://core.trac.wordpress.org/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.

    ```notranslate
    {
      "type": "string",
      "minLength": 2,
      "maxLength": 4
    }
    ```

The `exclusiveMinimum` and `exclusiveMaximum` keywords do not apply, they are only
valid for numbers.

Relevant changeset: [[47627]](https://core.trac.wordpress.org/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.

    ```notranslate
    {
      "type": "array",
      "minItems": 1,
      "maxItems": 2,
      "items": {
        "type": "string"
      }
    }
    ```

Again, the `exclusiveMinimum` and `exclusiveMaximum` keywords do not apply.

Relevante changeset: [[47923]](https://core.trac.wordpress.org/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.

    ```notranslate
    {
      "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.

    ```notranslate
    [
      [ "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.

    ```notranslate
    [
      { 
        "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:

    ```notranslate
    {
      "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](https://core.trac.wordpress.org/ticket/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]](https://core.trac.wordpress.org/changeset/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.

    ```notranslate
    {
      "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](https://core.trac.wordpress.org/ticket/49270)).
 * The `uuid` format has been introduced. This enforces a `uuid` of any version 
   using the `wp_is_uuid` function (see [#50053](https://core.trac.wordpress.org/ticket/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](https://core.trac.wordpress.org/ticket/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](https://core.trac.wordpress.org/ticket/48821)).

_Props [@desrosj](https://profiles.wordpress.org/desrosj/), [@davidbaumwald](https://profiles.wordpress.org/davidbaumwald/),
and [@justinahinon](https://profiles.wordpress.org/justinahinon/) for reviewing._

[#5-5](https://make.wordpress.org/core/tag/5-5/), [#dev-notes](https://make.wordpress.org/core/tag/dev-notes/),
[#rest-api](https://make.wordpress.org/core/tag/rest-api/)

### Share this:

 * [  Threads ](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?share=threads)
 * [  Mastodon ](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?share=mastodon)
 * [  Bluesky ](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?share=bluesky)
 * [  X ](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?share=x)
 * [  Facebook ](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?share=facebook)
 * [  LinkedIn ](https://make.wordpress.org/core/2020/07/16/rest-api-parameter-json-schema-changes-in-wordpress-5-5/?share=linkedin)

# Post navigation

[← Dev Chat Summary, July 15th, 2020](https://make.wordpress.org/core/2020/07/16/dev-chat-summary-july-15th-2020/)

[New and modified REST API endpoints in WordPress 5.5 →](https://make.wordpress.org/core/2020/07/16/new-and-modified-rest-api-endpoints-in-wordpress-5-5/)