Abstract base class for all Data Value Objects in the AI Client.
Description
This abstract class consolidates the common functionality needed by all data transfer objects:
- Array transformation for data manipulation
- JSON schema support for validation and documentation
- JSON serialization with proper empty object handling
All DTOs in the AI Client should extend this class to ensure consistent behavior across the codebase.
Methods
| Name | Description |
|---|---|
| AbstractDataTransferObject::convertEmptyArraysToObjects | Recursively converts empty arrays to stdClass objects where the schema expects objects. |
| AbstractDataTransferObject::isArrayShape | {@inheritDoc} |
| AbstractDataTransferObject::jsonSerialize | Converts the object to a JSON-serializable format. |
| AbstractDataTransferObject::validateFromArrayData | Validates that required keys exist in the array data. |
Source
abstract class AbstractDataTransferObject implements WithArrayTransformationInterface, WithJsonSchemaInterface, JsonSerializable
{
/**
* Validates that required keys exist in the array data.
*
* @since 0.1.0
*
* @param array<mixed> $data The array data to validate.
* @param string[] $requiredKeys The keys that must be present.
* @throws InvalidArgumentException If any required key is missing.
*/
protected static function validateFromArrayData(array $data, array $requiredKeys): void
{
$missingKeys = [];
foreach ($requiredKeys as $key) {
if (!array_key_exists($key, $data)) {
$missingKeys[] = $key;
}
}
if (!empty($missingKeys)) {
throw new InvalidArgumentException(sprintf('%s::fromArray() missing required keys: %s', static::class, implode(', ', $missingKeys)));
}
}
/**
* {@inheritDoc}
*
* @since 0.1.0
*/
public static function isArrayShape(array $array): bool
{
try {
/** @var TArrayShape $array */
static::fromArray($array);
return \true;
} catch (InvalidArgumentException $e) {
return \false;
}
}
/**
* Converts the object to a JSON-serializable format.
*
* This method uses the toArray() method and then processes the result
* based on the JSON schema to ensure proper object representation for
* empty arrays.
*
* @since 0.1.0
*
* @return mixed The JSON-serializable representation.
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$data = $this->toArray();
$schema = static::getJsonSchema();
return $this->convertEmptyArraysToObjects($data, $schema);
}
/**
* Recursively converts empty arrays to stdClass objects where the schema expects objects.
*
* @since 0.1.0
*
* @param mixed $data The data to process.
* @param array<mixed, mixed> $schema The JSON schema for the data.
* @return mixed The processed data.
*/
private function convertEmptyArraysToObjects($data, array $schema)
{
// If data is an empty array and schema expects object, convert to stdClass
if (is_array($data) && empty($data) && isset($schema['type']) && $schema['type'] === 'object') {
return new stdClass();
}
// If data is an array with content, recursively process nested structures
if (is_array($data)) {
// Handle object properties
if (isset($schema['properties']) && is_array($schema['properties'])) {
foreach ($data as $key => $value) {
if (isset($schema['properties'][$key]) && is_array($schema['properties'][$key])) {
$data[$key] = $this->convertEmptyArraysToObjects($value, $schema['properties'][$key]);
}
}
}
// Handle array items
if (isset($schema['items']) && is_array($schema['items'])) {
foreach ($data as $index => $item) {
$data[$index] = $this->convertEmptyArraysToObjects($item, $schema['items']);
}
}
// Handle oneOf/anyOf schemas - just use the first one
foreach (['oneOf', 'anyOf'] as $keyword) {
if (isset($schema[$keyword]) && is_array($schema[$keyword])) {
foreach ($schema[$keyword] as $possibleSchema) {
if (is_array($possibleSchema)) {
return $this->convertEmptyArraysToObjects($data, $possibleSchema);
}
}
}
}
}
return $data;
}
}
Changelog
| Version | Description |
|---|---|
| 0.1.0 | Introduced. |
User Contributed Notes
You must log in before being able to contribute a note or feedback.