Skip to content

Commit

Permalink
improve naming strategy handing by wrapping always custom naming stra…
Browse files Browse the repository at this point in the history
…tegies with the custom serialized name strategy
  • Loading branch information
goetas committed Aug 9, 2019
1 parent 9b8d643 commit b1a84fb
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 12 deletions.
1 change: 1 addition & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private function addSerializersSection(NodeBuilder $builder)
->end()
->children()
->scalarNode('id')->cannotBeEmpty()->end()
->booleanNode('allow_custom_serialized_name')->defaultValue(true)->end()
->scalarNode('separator')->defaultValue('_')->end()
->booleanNode('lower_case')->defaultTrue()->end()
->end()
Expand Down
12 changes: 9 additions & 3 deletions DependencyInjection/JMSSerializerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -49,13 +50,19 @@ public function loadInternal(array $config, ContainerBuilder $container)
->replaceArgument(2, $config['object_constructors']['doctrine']['fallback_strategy']);

// property naming
$namingStrategyServiceId = $config['property_naming']['id'] ?? 'jms_serializer.camel_case_naming_strategy';
$container
->getDefinition('jms_serializer.camel_case_naming_strategy')
->addArgument($config['property_naming']['separator'])
->addArgument($config['property_naming']['lower_case']);

if (!empty($config['property_naming']['id'])) {
$container->setAlias('jms_serializer.naming_strategy', $config['property_naming']['id']);
$container->setAlias('jms_serializer.naming_strategy', $namingStrategyServiceId);

if (!empty($config['property_naming']['allow_custom_serialized_name'])) {
$container
->register($namingStrategyServiceId . '.decorated', SerializedNameAnnotationStrategy::class)
->setDecoratedService($namingStrategyServiceId)
->addArgument(new Reference($namingStrategyServiceId. '.decorated.inner'));
}

$bundles = $container->getParameter('kernel.bundles');
Expand All @@ -72,7 +79,6 @@ public function loadInternal(array $config, ContainerBuilder $container)
$container
->getDefinition('jms_serializer.accessor_strategy.default')
->setArgument(0, new Reference($config['expression_evaluator']['id']));

} else {
$container->removeDefinition('jms_serializer.expression_evaluator');
}
Expand Down
5 changes: 1 addition & 4 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,8 @@
<!-- Naming Strategies -->
<service id="jms_serializer.camel_case_naming_strategy" class="JMS\Serializer\Naming\CamelCaseNamingStrategy" public="false" />
<service id="jms_serializer.identical_property_naming_strategy" class="JMS\Serializer\Naming\IdenticalPropertyNamingStrategy" public="false" />
<service id="jms_serializer.serialized_name_annotation_strategy" class="JMS\Serializer\Naming\SerializedNameAnnotationStrategy" public="false">
<argument type="service" id="jms_serializer.camel_case_naming_strategy" />
</service>

<service id="jms_serializer.naming_strategy" alias="jms_serializer.serialized_name_annotation_strategy" public="false" />
<service id="jms_serializer.naming_strategy" alias="jms_serializer.camel_case_naming_strategy" public="false" />

<!-- Object Constructors -->
<service id="jms_serializer.doctrine_object_constructor" class="JMS\Serializer\Construction\DoctrineObjectConstructor" public="false">
Expand Down
3 changes: 2 additions & 1 deletion Resources/doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ values:
fallback_strategy: "null" # possible values ("null" | "exception" | "fallback")
property_naming:
id: ~
id: ~ # service id for a custom naming strategy to use, separator and lower_case will be ignored
allow_custom_serialized_name: true # consider @SerializedName annotation
separator: _
lower_case: true
Expand Down
60 changes: 56 additions & 4 deletions Tests/DependencyInjection/NamingStrategyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace JMS\SerializerBundle\Tests\DependencyInjection;

use Doctrine\Common\Annotations\AnnotationReader;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\SerializerBundle\DependencyInjection\JMSSerializerExtension;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

class NamingStrategyTest extends TestCase
{
Expand All @@ -24,21 +27,70 @@ private function getContainer(array $configs = array())
$container->setParameter('kernel.cache_dir', sys_get_temp_dir() . '/serializer');
$container->setParameter('kernel.bundles', array());

$container->setDefinition("annotation_reader", new Definition(AnnotationReader::class));
$container->setDefinition("custom_naming_strategy", new Definition(CustomNamingStrategy::class));

$loader->load(['jms_serializer' => $configs], $container);

// set public only for testing
$container->getAlias('jms_serializer.naming_strategy')->setPublic(true);

$container->compile();
return $container;
}

public function testCustomNamingStrategy()
public function testDefaultNamingStrategy()
{
$container = $this->getContainer();

$strategy = $container->get('jms_serializer.naming_strategy');
$this->assertInstanceOf(SerializedNameAnnotationStrategy::class, $strategy);

$property = new PropertyMetadata(\stdClass::class, 'propOne');
self::assertSame('prop_one', $strategy->translateName($property));

$property = new PropertyMetadata(\stdClass::class, 'propOne');
$property->serializedName = 'abc';
self::assertSame('abc', $strategy->translateName($property));
}

public function testCustomNamingStrategyIsWrappedBySerializedNameAnnotationStrategy()
{
$container = $this->getContainer(array(
'property_naming' => array(
'id' => 'custom_naming_strategy',
)
));

$strategy = $container->get('jms_serializer.naming_strategy');
$this->assertInstanceOf(SerializedNameAnnotationStrategy::class, $strategy);

$property = new PropertyMetadata(\stdClass::class, 'prop1');
self::assertSame('foo', $strategy->translateName($property));

$property = new PropertyMetadata(\stdClass::class, 'prop1');
$property->serializedName = 'abc';
self::assertSame('abc', $strategy->translateName($property));
}

public function testCustomNamingStrategyWrapCanBeDisabled()
{
$container = $this->getContainer(array(
'property_naming' => array(
'id' => 'custom_naming_strategy',
'allow_custom_serialized_name' => false,
)
));
$customNamingStrategy = new CustomNamingStrategy();
$container->set("custom_naming_strategy", $customNamingStrategy);

$this->assertSame($customNamingStrategy, $container->get('jms_serializer.naming_strategy'));
$strategy = $container->get('jms_serializer.naming_strategy');
$this->assertInstanceOf(CustomNamingStrategy::class, $strategy);

$property = new PropertyMetadata(\stdClass::class, 'prop1');
self::assertSame('foo', $strategy->translateName($property));

$property = new PropertyMetadata(\stdClass::class, 'prop1');
$property->serializedName = 'abc';
self::assertSame('foo', $strategy->translateName($property));
}
}

Expand Down

0 comments on commit b1a84fb

Please sign in to comment.