I have registered settings and need it to be showed in REST API.
$args = [
'show_in_rest' => true
];
register_setting('default_sidebars', 'default_sidebars', $args);
When I save a single value and then request data on endpoint /wp-json/wp/v2/settings
, everything works perfectly.
But the problem is that I save serialized data like this.
a:2:{s:4:"post";s:7:"general";s:4:"blog";s:9:"sidebar_1";}
Now I would expect in response something like this:
default_sidebars: {
post: "general",
blog: "sidebar_1"
}
But instead I got default_sidebars: null
.
What should I do to get my data in REST API?
I have registered settings and need it to be showed in REST API.
$args = [
'show_in_rest' => true
];
register_setting('default_sidebars', 'default_sidebars', $args);
When I save a single value and then request data on endpoint /wp-json/wp/v2/settings
, everything works perfectly.
But the problem is that I save serialized data like this.
a:2:{s:4:"post";s:7:"general";s:4:"blog";s:9:"sidebar_1";}
Now I would expect in response something like this:
default_sidebars: {
post: "general",
blog: "sidebar_1"
}
But instead I got default_sidebars: null
.
What should I do to get my data in REST API?
Share Improve this question asked Mar 7, 2020 at 15:09 Tomáš VavřinkaTomáš Vavřinka 1979 bronze badges2 Answers
Reset to default 6JSON Schema
It's supported if you explicitly register the object JSON schema as:
$args = array(
'show_in_rest' => array(
'schema' => array(
'type' => 'object',
'properties' => array(
'post' => array(
'type' => 'string',
),
'blog' => array(
'type' => 'string',
),
)
),
),
);
register_setting( 'default_sidebars', 'default_sidebars', $args );
Resulting in the following object:
default_sidebars: {
post: "general",
blog: "sidebar_1"
}
in /wp-json/wp/v2/settings
for the serialized option data:
a:2:{s:4:"post";s:7:"general";s:4:"blog";s:9:"sidebar_1";}
See similar object schema support for register_meta()
in 5.3:
https://make.wordpress/core/2019/10/03/wp-5-3-supports-object-and-array-meta-types-in-the-rest-api/
Not sure if there's a better way when using the default Settings endpoint, but this works for me.
You can use the rest_pre_get_setting
hook to convert the data to a JSON-encoded string:
add_filter( 'rest_pre_get_setting', function ( $value, $name ) {
if ( 'default_sidebars' === $name ) {
$value = json_encode( get_option( $name ) );
}
return $value;
}, 10, 2 );
Then for example in JavaScript, you can parse the value into an object using JSON.parse()
:
// Note: I intentionally omitted the authentication/nonce part.
fetch( 'https://example/wp-json/wp/v2/settings' )
.then( res => res.json() )
.then( settings => console.log( JSON.parse( settings.default_sidebars ) ) );
Or in PHP (e.g. you make the API request from another site using PHP), you can do:
$settings = json_decode( $data ); // assume data is the REST API response body
$default_sidebars = json_decode( $settings->default_sidebars );
Additional Notes
The null
value is because get_option()
unserializes the data to an array and the REST API controller for the Settings endpoint is using rest_validate_value_from_schema()
to validate the option value (i.e. after being unserialized), which when it's not of the currently supported types (string, boolean, integer and number) — see register_setting()
, then the function returns an error and the Settings endpoint/controller returns a null
for that specific option.
Alternate Solution
You can create a custom REST API endpoint and with the following example, you would make request to /wp-json/myplugin/v1/setting/<option name>
where <option name>
could be default_sidebars
in your case:
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/setting/(?P<name>[a-zA-Z0-9\-_]+)', [
'methods' => 'GET',
'callback' => function ( $request ) {
return get_option( $request->get_param( 'name' ) );
},
'permission_callback' => function () {
return current_user_can( 'manage_options' ); // you should keep this
},
] );
} );