WP_REST_View_Config_Controller::cast_empty_objects( mixed $value, array $schema ): mixed

Recursively casts empty arrays to objects where the schema types them as objects.

Description

PHP cannot distinguish an empty associative array from an empty list, so json_encode() always serializes array() as a JSON array ([]). The REST schema, however, types several values as objects, which must encode as {}. This walks the value against its schema and casts any empty, object-typed array to an object. Non-empty associative arrays already encode as objects, so they are left as arrays and only recursed into to fix any nested empty objects.

Union schemas (oneOf/anyOf) are handled only for the empty-array case: an empty value is cast to an object when any branch allows an object. Such values are not recursed into, which is sufficient for the form schema where they never contain empty nested objects.

Parameters

$valuemixedrequired
The value to normalize.
$schemaarrayrequired
The schema node describing the value.

Return

mixed The normalized value, with empty object-typed arrays cast to objects.

Source

protected function cast_empty_objects( $value, $schema ) {
	if ( ! is_array( $value ) || ! is_array( $schema ) ) {
		return $value;
	}

	if ( isset( $schema['oneOf'] ) || isset( $schema['anyOf'] ) ) {
		$branches = $schema['oneOf'] ?? $schema['anyOf'];
		if ( array() === $value ) {
			foreach ( $branches as $branch ) {
				if ( is_array( $branch ) && in_array( 'object', (array) ( $branch['type'] ?? array() ), true ) ) {
					return (object) array();
				}
			}
		}
		return $value;
	}

	$types = (array) ( $schema['type'] ?? array() );

	if ( in_array( 'array', $types, true ) && isset( $schema['items'] ) ) {
		foreach ( $value as $index => $item ) {
			$value[ $index ] = $this->cast_empty_objects( $item, $schema['items'] );
		}
		return $value;
	}

	if ( in_array( 'object', $types, true ) ) {
		if ( isset( $schema['properties'] ) ) {
			foreach ( $schema['properties'] as $property => $property_schema ) {
				if ( array_key_exists( $property, $value ) ) {
					$value[ $property ] = $this->cast_empty_objects( $value[ $property ], $property_schema );
				}
			}
		}
		if ( isset( $schema['additionalProperties'] ) && is_array( $schema['additionalProperties'] ) ) {
			foreach ( $value as $key => $item ) {
				if ( isset( $schema['properties'][ $key ] ) ) {
					continue;
				}
				$value[ $key ] = $this->cast_empty_objects( $item, $schema['additionalProperties'] );
			}
		}

		// Empty object-typed arrays must serialize as {} to match the schema.
		if ( array() === $value ) {
			return (object) array();
		}
	}

	return $value;
}

Changelog

VersionDescription
7.1.0Introduced.

User Contributed Notes

You must log in before being able to contribute a note or feedback.