mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-10 03:29:25 +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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type = $this->getNestedTypeInArray($item)) {
|
if ($nestedType = $this->getNestedTypeInArray($item)) {
|
||||||
$property->setType('array');
|
list($type, $isHash) = $nestedType;
|
||||||
$property = $property->getItems();
|
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 {
|
} else {
|
||||||
$type = $item->type['name'];
|
$type = $item->type['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($type, ['boolean', 'string', 'array'])) {
|
$typeDef = $this->findPropertyType($type, $groups);
|
||||||
$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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$property->setRef(
|
// virtual property
|
||||||
$this->modelRegistry->register(new Model(new Type(Type::BUILTIN_TYPE_OBJECT, false, $type), $groups))
|
if (!$typeDef) {
|
||||||
);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->registerPropertyType($typeDef, $property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,20 +139,74 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn
|
|||||||
return false;
|
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)
|
private function getNestedTypeInArray(PropertyMetadata $item)
|
||||||
{
|
{
|
||||||
if ('array' !== $item->type['name'] && 'ArrayCollection' !== $item->type['name']) {
|
if ('array' !== $item->type['name'] && 'ArrayCollection' !== $item->type['name']) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// array<string, MyNamespaceMyObject>
|
// array<string, MyNamespaceMyObject>
|
||||||
if (isset($item->type['params'][1]['name'])) {
|
if (isset($item->type['params'][1]['name'])) {
|
||||||
return $item->type['params'][1]['name'];
|
return [$item->type['params'][1]['name'], true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// array<MyNamespaceMyObject>
|
// array<MyNamespaceMyObject>
|
||||||
if (isset($item->type['params'][0]['name'])) {
|
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;
|
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\Type("integer")
|
||||||
* @Serializer\Expose
|
* @Serializer\Expose
|
||||||
|
@ -54,6 +54,19 @@ class JMSFunctionalTest extends WebTestCase
|
|||||||
'$ref' => '#/definitions/User',
|
'$ref' => '#/definitions/User',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'indexed_friends' => [
|
||||||
|
'type' => 'object',
|
||||||
|
'additionalProperties' => [
|
||||||
|
'$ref' => '#/definitions/User',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'favorite_dates' => [
|
||||||
|
'type' => 'object',
|
||||||
|
'additionalProperties' => [
|
||||||
|
'type' => 'string',
|
||||||
|
'format' => 'date-time',
|
||||||
|
],
|
||||||
|
],
|
||||||
'best_friend' => [
|
'best_friend' => [
|
||||||
'$ref' => '#/definitions/User',
|
'$ref' => '#/definitions/User',
|
||||||
],
|
],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user