mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-09 02:59:27 +03:00
Improve support for JMS dictionaries (associative arrays) (#1301)
* improve support for JMS dictionaries (associative arrays) Doc: https://swagger.io/docs/specification/data-models/dictionaries/ * use schema merge instead of reflection
This commit is contained in:
parent
1680ba3481
commit
c5b1d538f8
@ -92,33 +92,33 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type = $this->getNestedTypeInArray($item)) {
|
||||
$property->setType('array');
|
||||
$property = $property->getItems();
|
||||
if ($nestedType = $this->getNestedTypeInArray($item)) {
|
||||
list($type, $isHash) = $nestedType;
|
||||
if ($isHash) {
|
||||
$property->setType('object');
|
||||
|
||||
$typeDef = $this->findPropertyType($type, $groups);
|
||||
|
||||
// in the case of a virtual property, set it as free object type
|
||||
$property->merge(['additionalProperties' => $typeDef ?: []]);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
$property->setType('array');
|
||||
$property = $property->getItems();
|
||||
}
|
||||
} else {
|
||||
$type = $item->type['name'];
|
||||
}
|
||||
|
||||
if (in_array($type, ['boolean', 'string', 'array'])) {
|
||||
$property->setType($type);
|
||||
} elseif (in_array($type, ['int', 'integer'])) {
|
||||
$property->setType('integer');
|
||||
} elseif (in_array($type, ['double', 'float'])) {
|
||||
$property->setType('number');
|
||||
$property->setFormat($type);
|
||||
} elseif (in_array($type, ['DateTime', 'DateTimeImmutable'])) {
|
||||
$property->setType('string');
|
||||
$property->setFormat('date-time');
|
||||
} else {
|
||||
// we can use property type also for custom handlers, then we don't have here real class name
|
||||
if (!class_exists($type)) {
|
||||
continue;
|
||||
}
|
||||
$typeDef = $this->findPropertyType($type, $groups);
|
||||
|
||||
$property->setRef(
|
||||
$this->modelRegistry->register(new Model(new Type(Type::BUILTIN_TYPE_OBJECT, false, $type), $groups))
|
||||
);
|
||||
// virtual property
|
||||
if (!$typeDef) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->registerPropertyType($typeDef, $property);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,20 +139,74 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param array|null $groups
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function findPropertyType(string $type, array $groups = null)
|
||||
{
|
||||
$typeDef = [];
|
||||
if (in_array($type, ['boolean', 'string', 'array'])) {
|
||||
$typeDef['type'] = $type;
|
||||
} elseif (in_array($type, ['int', 'integer'])) {
|
||||
$typeDef['type'] = 'integer';
|
||||
} elseif (in_array($type, ['double', 'float'])) {
|
||||
$typeDef['type'] = 'number';
|
||||
$typeDef['format'] = $type;
|
||||
} elseif (in_array($type, ['DateTime', 'DateTimeImmutable'])) {
|
||||
$typeDef['type'] = 'string';
|
||||
$typeDef['format'] = 'date-time';
|
||||
} else {
|
||||
// we can use property type also for custom handlers, then we don't have here real class name
|
||||
if (!class_exists($type)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$typeDef['$ref'] = $this->modelRegistry->register(
|
||||
new Model(new Type(Type::BUILTIN_TYPE_OBJECT, false, $type), $groups)
|
||||
);
|
||||
}
|
||||
|
||||
return $typeDef;
|
||||
}
|
||||
|
||||
private function registerPropertyType(array $typeDef, $property)
|
||||
{
|
||||
if (isset($typeDef['$ref'])) {
|
||||
$property->setRef($typeDef['$ref']);
|
||||
} else {
|
||||
if (isset($typeDef['type'])) {
|
||||
$property->setType($typeDef['type']);
|
||||
}
|
||||
if (isset($typeDef['format'])) {
|
||||
$property->setFormat($typeDef['format']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PropertyMetadata $item
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getNestedTypeInArray(PropertyMetadata $item)
|
||||
{
|
||||
if ('array' !== $item->type['name'] && 'ArrayCollection' !== $item->type['name']) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// array<string, MyNamespaceMyObject>
|
||||
if (isset($item->type['params'][1]['name'])) {
|
||||
return $item->type['params'][1]['name'];
|
||||
return [$item->type['params'][1]['name'], true];
|
||||
}
|
||||
|
||||
// array<MyNamespaceMyObject>
|
||||
if (isset($item->type['params'][0]['name'])) {
|
||||
return $item->type['params'][0]['name'];
|
||||
return [$item->type['params'][0]['name'], false];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,17 @@ class JMSUser
|
||||
*/
|
||||
private $friends;
|
||||
|
||||
/**
|
||||
* @Serializer\Type("array<string, Nelmio\ApiDocBundle\Tests\Functional\Entity\User>")
|
||||
* @Serializer\Expose
|
||||
*/
|
||||
private $indexedFriends;
|
||||
|
||||
/**
|
||||
* @Serializer\Type("array<string, DateTime>")
|
||||
* @Serializer\Expose
|
||||
*/
|
||||
private $favoriteDates;
|
||||
/**
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\Expose
|
||||
|
@ -54,6 +54,19 @@ class JMSFunctionalTest extends WebTestCase
|
||||
'$ref' => '#/definitions/User',
|
||||
],
|
||||
],
|
||||
'indexed_friends' => [
|
||||
'type' => 'object',
|
||||
'additionalProperties' => [
|
||||
'$ref' => '#/definitions/User',
|
||||
],
|
||||
],
|
||||
'favorite_dates' => [
|
||||
'type' => 'object',
|
||||
'additionalProperties' => [
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
],
|
||||
],
|
||||
'best_friend' => [
|
||||
'$ref' => '#/definitions/User',
|
||||
],
|
||||
|
Loading…
x
Reference in New Issue
Block a user