Add @SerializedName support (#1636)

* Add `@SerializedName` support

* Also test `@SerializedName` on properties

* Fix tests with sf < 4.2

* Fix the tests

* Update the CHANGELOG
This commit is contained in:
Guilhem Niot 2020-05-30 18:08:25 +02:00 committed by GitHub
parent 5e8f7290e8
commit dfff2476d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 113 additions and 5 deletions

View File

@ -1,10 +1,15 @@
CHANGELOG
=========
3.3.0 (unreleased)
3.7.0 (unreleased)
------------------
* Usage of Google Fonts was removed. System fonts `serif` / `sans` will be used instead.
* Added `@SerializedName` annotation support and name converters when using Symfony >= 4.2.
3.3.0
-----
* Usage of Google Fonts was removed. System fonts `serif` / `sans` will be used instead.
This can lead to a different look on different operating systems.
You can [re-add Google Fonts again manually by overriding the template](https://symfony.com/doc/current/bundles/NelmioApiDocBundle/faq.html#re-add-google-fonts).

View File

@ -20,6 +20,7 @@ use Nelmio\ApiDocBundle\ModelDescriber\Annotations\AnnotationsReader;
use Nelmio\ApiDocBundle\PropertyDescriber\PropertyDescriberInterface;
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwareInterface
{
@ -31,17 +32,21 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
private $doctrineReader;
/** @var PropertyDescriberInterface[] */
private $propertyDescribers;
/** @var NameConverterInterface[] */
private $nameConverter;
private $swaggerDefinitionAnnotationReader;
public function __construct(
PropertyInfoExtractorInterface $propertyInfo,
Reader $reader,
$propertyDescribers
$propertyDescribers,
NameConverterInterface $nameConverter = null
) {
$this->propertyInfo = $propertyInfo;
$this->doctrineReader = $reader;
$this->propertyDescribers = $propertyDescribers;
$this->nameConverter = $nameConverter;
}
public function describe(Model $model, Schema $schema)
@ -64,10 +69,12 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
}
foreach ($propertyInfoProperties as $propertyName) {
$serializedName = null !== $this->nameConverter ? $this->nameConverter->normalize($propertyName, $class, null, null !== $model->getGroups() ? ['groups' => $model->getGroups()] : []) : $propertyName;
// read property options from Swagger Property annotation if it exists
if (property_exists($class, $propertyName)) {
$reflectionProperty = new \ReflectionProperty($class, $propertyName);
$property = $properties->get($annotationsReader->getPropertyName($reflectionProperty, $propertyName));
$property = $properties->get($annotationsReader->getPropertyName($reflectionProperty, $serializedName));
$groups = $model->getGroups();
if (isset($groups[$propertyName]) && is_array($groups[$propertyName])) {
@ -76,7 +83,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
$annotationsReader->updateProperty($reflectionProperty, $property, $groups);
} else {
$property = $properties->get($propertyName);
$property = $properties->get($serializedName);
}
// If type manually defined

View File

@ -42,6 +42,7 @@
<argument type="service" id="property_info" />
<argument type="service" id="annotation_reader" />
<argument type="tagged" tag="nelmio_api_doc.object_model.property_describer" />
<argument type="service" id="serializer.name_converter.metadata_aware" on-invalid="ignore" />
<tag name="nelmio_api_doc.model_describer" />
</service>

View File

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Tests\Functional\Controller;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\SerializedNameEnt;
use Swagger\Annotations as SWG;
use Symfony\Component\Routing\Annotation\Route;
/**
* This controller is only loaded when SerializedName exists (sf >= 4.2).
*
* @Route("/api", host="api.example.com")
*/
class SerializedNameController
{
/**
* @SWG\Response(
* response="200",
* description="success",
* @Model(type=SerializedNameEnt::class)
* )
* @Route("/serializename", methods={"GET"})
*/
public function serializedNameAction()
{
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded;
use Symfony\Component\Serializer\Annotation\SerializedName;
/**
* @author Guilhem N. <guilhem.niot@gmail.com>
*/
class SerializedNameEnt
{
/**
* @SerializedName("notfoo")
*
* @var string
*/
public $foo;
/**
* Tests serialized name feature.
*
* @SerializedName("notwhatyouthink")
*/
public function setBar(string $bar)
{
}
}

View File

@ -12,6 +12,7 @@
namespace Nelmio\ApiDocBundle\Tests\Functional;
use EXSyst\Component\Swagger\Tag;
use Symfony\Component\Serializer\Annotation\SerializedName;
class FunctionalTest extends WebTestCase
{
@ -407,4 +408,20 @@ class FunctionalTest extends WebTestCase
{
$this->assertFalse($this->getOperation('/api/article/{id}', 'get')->getParameters()->has('id', 'path'));
}
public function testSerializedNameAction()
{
if (!class_exists(SerializedName::class)) {
$this->markTestSkipped('Annotation @SerializedName doesn\'t exist.');
}
$modelProperties = $this->getModel('SerializedNameEnt')->getProperties();
$this->assertCount(2, $modelProperties);
$this->assertFalse($modelProperties->has('foo'));
$this->assertTrue($modelProperties->has('notfoo'));
$this->assertFalse($modelProperties->has('bar'));
$this->assertTrue($modelProperties->has('notwhatyouthink'));
}
}

View File

@ -29,6 +29,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
use Symfony\Component\Serializer\Annotation\SerializedName;
class TestKernel extends Kernel
{
@ -87,6 +88,10 @@ class TestKernel extends Kernel
$routes->add('/docs/{area}', 'nelmio_api_doc.controller.swagger_ui')->setDefault('area', 'default');
$routes->add('/docs.json', 'nelmio_api_doc.controller.swagger');
if (class_exists(SerializedName::class)) {
$routes->import(__DIR__.'/Controller/SerializedNameController.php', '/', 'annotation');
}
if (class_exists(FOSRestBundle::class)) {
$routes->import(__DIR__.'/Controller/FOSRestController.php', '/', 'annotation');
}