wp-json-schema-api
Prepare, expose, and audit WordPress-authored JSON Schemas with the WordPress 7.1 JSON Schema API. Covers wp_prepare_json_schema_for_client, wp_get_json_schema_allowed_keywords, draft-04 versus rest-api profiles, required-property conversion, recursive schema cleanup, empty-objec
Install
npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/wordpress/wp-json-schema-api
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
git clone https://github.com/Lonsdale201/wp-agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
WordPress JSON Schema API
WordPress 7.1 adds a shared API for preparing WordPress-authored schemas for clients. Its job is compatibility and safe publication: it converts a few WordPress conventions and removes keywords outside the selected profile. It does not validate or sanitize a value and does not authorize an operation.
Use the public helpers
Feature-detect when WordPress 7.0 or older remains supported:
if ( function_exists( 'wp_prepare_json_schema_for_client' ) ) {
$public_schema = wp_prepare_json_schema_for_client( $schema, 'draft-04' );
} else {
// Keep a deliberately maintained compatibility schema; do not expose
// callbacks or blindly return the server schema.
$public_schema = $legacy_public_schema;
}
The two public functions have deliberately different defaults:
wp_get_json_schema_allowed_keywords()defaults torest-api;wp_prepare_json_schema_for_client()defaults todraft-04.
Choose rest-api for the historical REST-exposed keyword subset. Choose
draft-04 for a standalone client, Ability description, or AI provider that
can consume the broader Draft 4 vocabulary. An unknown profile falls back to
the REST keyword set; do not rely on misspelled profile names failing closed
with an exception.
Keep server and published schemas separate
$server_schema = array(
'type' => 'object',
'properties' => array(
'post_id' => array(
'type' => 'integer',
'minimum' => 1,
'required' => true,
'sanitize_callback' => 'absint',
),
),
);
$public_schema = wp_prepare_json_schema_for_client(
$server_schema,
'draft-04'
);
The published result moves the per-property required: true marker into the
parent object's required array and strips the callable. Keep the original
schema for WordPress execution and the prepared copy for transport.
If the parent already has a Draft 4 required array, it takes precedence:
per-property booleans are removed but are not merged into that array. Make the
server contract internally consistent before publishing it.
Understand what preparation changes
Preparation recursively walks schema-bearing keywords, removes keys not allowed by the profile, and normalizes WordPress-specific representations. In particular:
- an empty array used as the default of an object schema becomes a JSON object;
- per-property boolean
requiredflags are removed and, when no parentrequiredarray exists, thetrueproperties are collected there; - a stray boolean
requiredwithout an object property list is removed; - nested
properties,patternProperties,definitions,dependencies,items,not,additionalProperties,additionalItems,anyOf,oneOf, andallOfschemas are prepared recursively when the chosen profile permits those keywords; - unknown and WordPress-only keys, including PHP callbacks, are removed.
Numeric arrays used as data, such as property-dependency lists, are preserved instead of being mistaken for schema maps.
Read references/profiles-and-normalization.md for the exact profile delta and
review probes.
Validation, sanitization, and authorization remain separate
Never treat a prepared schema as evidence that input was checked:
- validate inbound data with the API that owns the request, such as
rest_validate_value_from_schema()or the registered REST argument schema; - sanitize/coerce only according to that server contract;
- perform capability and object-ownership checks separately;
- copy allowlisted fields into the write model rather than mass-assigning a request object.
Adding a keyword through wp_json_schema_allowed_keywords only allows that
keyword to survive publication. It does not teach WordPress validators or
sanitizers how to enforce it. A plugin that adds const, if, or a custom
keyword must also own and test the corresponding validation behavior.
Filter safely
The filter receives the allowed keyword list and profile name:
add_filter(
'wp_json_schema_allowed_keywords',
static function ( array $keywords, string $profile ): array {
if ( 'draft-04' !== $profile ) {
return $keywords;
}
$keywords[] = 'x-acme-ui';
return array_values( array_unique( $keywords ) );
},
10,
2
);
Only extend the list for a namespaced, documented consumer contract. A global filter affects every schema prepared later in the request, including core and other plugins. Keep it deterministic, avoid removing standard keywords, and test for cross-plugin collisions.
Review checklist
- Confirm the target consumer and select
rest-apiordraft-04explicitly. - Keep the execution schema distinct from its prepared transport copy.
- Inspect the prepared output with
wp_json_encode(), especially empty object defaults and nested schemas. - Verify parent
requiredarrays and per-property markers do not disagree. - Confirm no callable, internal metadata, secret default, or implementation detail survives publication.
- Validate and authorize actual inputs independently of schema preparation.
- Test custom allowed-keyword filters with other plugins active.
- Feature-detect the helpers or require WordPress 7.1.
Related skills
wp-rest-apifor server route schemas and request validation.wp-abilities-apifor Ability input/output contracts.wp-ai-clientfor structured AI output and function declarations.
References
- WordPress 7.1 core:
wp-includes/json-schema.php. - WordPress REST schema helpers:
wp-includes/rest-api.php. - https://make.wordpress.org/core/2026/07/31/json-schema-preparation-for-client-compatibility-in-wordpress-7-1/
Files (wp-agent-skills)
-
agents
-
openai.yaml 226 B
interface: display_name: "WordPress JSON Schema API" short_description: "Prepare safe client schemas with WordPress 7.1" default_prompt: "Use $wp-json-schema-api to prepare or audit this WordPress JSON Schema contract."
-
-
references
-
profiles-and-normalization.md 1.9 KB
# JSON Schema profiles and normalization ## Profile matrix Both profiles include the historical REST schema keywords returned by `rest_get_allowed_schema_keywords()`: descriptive fields, type/format/enum, object and array shape, numeric/string/array limits, and `anyOf` / `oneOf`. The `draft-04` profile additionally preserves: - `$schema`, `id`, and `$ref`; - parent-array `required`; - `allOf` and `not`; - `definitions` and `dependencies`; - `additionalItems`. The preparer only filters and normalizes the schema. Preservation is not a claim that `rest_validate_value_from_schema()` implements every preserved Draft 4 keyword. ## Before and after probe Input: ```php $schema = array( 'type' => 'object', 'default' => array(), 'properties' => array( 'name' => array( 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ), 'note' => array( 'type' => 'string', 'required' => false, ), ), ); $prepared = wp_prepare_json_schema_for_client( $schema, 'draft-04' ); ``` Expected properties of the result: - `default` is an object when encoded to JSON; - parent `required` is `array( 'name' )`; - neither property retains a boolean `required`; - `sanitize_callback` is absent. Do not compare the object default to an array with strict equality. Confirm the transport representation instead: ```php $json = wp_json_encode( $prepared ); ``` ## Failure probes - Pass an unknown profile and confirm it uses the REST subset. - Supply an existing parent `required` array and confirm it remains unchanged. - Nest object schemas in `items`, `additionalProperties`, and `oneOf` and check that private keys are removed recursively. - Add a keyword through `wp_json_schema_allowed_keywords`; confirm it survives output but is not magically enforced by REST validation. - Run the same filter beside another extension to detect request-global allowlist changes.
-
-
SKILL.md 6.5 KB
--- name: wp-json-schema-api description: >- Prepare, expose, and audit WordPress-authored JSON Schemas with the WordPress 7.1 JSON Schema API. Covers wp_prepare_json_schema_for_client, wp_get_json_schema_allowed_keywords, draft-04 versus rest-api profiles, required-property conversion, recursive schema cleanup, empty-object defaults, the wp_json_schema_allowed_keywords filter, and the boundary between schema publication, REST validation, sanitization, and application authorization. Use when returning schemas through REST, Abilities, AI tools, JavaScript configuration, or converting WordPress REST-style schemas for external consumers. license: GPLv2-or-later metadata: wp-skills-author: "Soczó Kristóf" wp-skills-contact: "mailto:lonsdale201@hotmail.com" wp-skills-plugin: "wordpress" wp-skills-plugin-version-tested: "7.1" wp-skills-wp-version-tested: "7.1" wp-skills-php-min: "7.4" wp-skills-last-updated: "2026-08-20" --- # WordPress JSON Schema API WordPress 7.1 adds a shared API for preparing WordPress-authored schemas for clients. Its job is compatibility and safe publication: it converts a few WordPress conventions and removes keywords outside the selected profile. It does not validate or sanitize a value and does not authorize an operation. ## Use the public helpers Feature-detect when WordPress 7.0 or older remains supported: ```php if ( function_exists( 'wp_prepare_json_schema_for_client' ) ) { $public_schema = wp_prepare_json_schema_for_client( $schema, 'draft-04' ); } else { // Keep a deliberately maintained compatibility schema; do not expose // callbacks or blindly return the server schema. $public_schema = $legacy_public_schema; } ``` The two public functions have deliberately different defaults: - `wp_get_json_schema_allowed_keywords()` defaults to `rest-api`; - `wp_prepare_json_schema_for_client()` defaults to `draft-04`. Choose `rest-api` for the historical REST-exposed keyword subset. Choose `draft-04` for a standalone client, Ability description, or AI provider that can consume the broader Draft 4 vocabulary. An unknown profile falls back to the REST keyword set; do not rely on misspelled profile names failing closed with an exception. ## Keep server and published schemas separate ```php $server_schema = array( 'type' => 'object', 'properties' => array( 'post_id' => array( 'type' => 'integer', 'minimum' => 1, 'required' => true, 'sanitize_callback' => 'absint', ), ), ); $public_schema = wp_prepare_json_schema_for_client( $server_schema, 'draft-04' ); ``` The published result moves the per-property `required: true` marker into the parent object's `required` array and strips the callable. Keep the original schema for WordPress execution and the prepared copy for transport. If the parent already has a Draft 4 `required` array, it takes precedence: per-property booleans are removed but are not merged into that array. Make the server contract internally consistent before publishing it. ## Understand what preparation changes Preparation recursively walks schema-bearing keywords, removes keys not allowed by the profile, and normalizes WordPress-specific representations. In particular: - an empty array used as the default of an object schema becomes a JSON object; - per-property boolean `required` flags are removed and, when no parent `required` array exists, the `true` properties are collected there; - a stray boolean `required` without an object property list is removed; - nested `properties`, `patternProperties`, `definitions`, `dependencies`, `items`, `not`, `additionalProperties`, `additionalItems`, `anyOf`, `oneOf`, and `allOf` schemas are prepared recursively when the chosen profile permits those keywords; - unknown and WordPress-only keys, including PHP callbacks, are removed. Numeric arrays used as data, such as property-dependency lists, are preserved instead of being mistaken for schema maps. Read `references/profiles-and-normalization.md` for the exact profile delta and review probes. ## Validation, sanitization, and authorization remain separate Never treat a prepared schema as evidence that input was checked: 1. validate inbound data with the API that owns the request, such as `rest_validate_value_from_schema()` or the registered REST argument schema; 2. sanitize/coerce only according to that server contract; 3. perform capability and object-ownership checks separately; 4. copy allowlisted fields into the write model rather than mass-assigning a request object. Adding a keyword through `wp_json_schema_allowed_keywords` only allows that keyword to survive publication. It does not teach WordPress validators or sanitizers how to enforce it. A plugin that adds `const`, `if`, or a custom keyword must also own and test the corresponding validation behavior. ## Filter safely The filter receives the allowed keyword list and profile name: ```php add_filter( 'wp_json_schema_allowed_keywords', static function ( array $keywords, string $profile ): array { if ( 'draft-04' !== $profile ) { return $keywords; } $keywords[] = 'x-acme-ui'; return array_values( array_unique( $keywords ) ); }, 10, 2 ); ``` Only extend the list for a namespaced, documented consumer contract. A global filter affects every schema prepared later in the request, including core and other plugins. Keep it deterministic, avoid removing standard keywords, and test for cross-plugin collisions. ## Review checklist - Confirm the target consumer and select `rest-api` or `draft-04` explicitly. - Keep the execution schema distinct from its prepared transport copy. - Inspect the prepared output with `wp_json_encode()`, especially empty object defaults and nested schemas. - Verify parent `required` arrays and per-property markers do not disagree. - Confirm no callable, internal metadata, secret default, or implementation detail survives publication. - Validate and authorize actual inputs independently of schema preparation. - Test custom allowed-keyword filters with other plugins active. - Feature-detect the helpers or require WordPress 7.1. ## Related skills - `wp-rest-api` for server route schemas and request validation. - `wp-abilities-api` for Ability input/output contracts. - `wp-ai-client` for structured AI output and function declarations. ## References - WordPress 7.1 core: `wp-includes/json-schema.php`. - WordPress REST schema helpers: `wp-includes/rest-api.php`. - <https://make.wordpress.org/core/2026/07/31/json-schema-preparation-for-client-compatibility-in-wordpress-7-1/>
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.