Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AdvancedNamingStrategyInterface #859

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/JMS/Serializer/AbstractVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

use JMS\Serializer\Accessor\AccessorStrategyInterface;
use JMS\Serializer\Accessor\DefaultAccessorStrategy;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;

abstract class AbstractVisitor implements VisitorInterface
{
Expand All @@ -31,7 +30,7 @@ abstract class AbstractVisitor implements VisitorInterface
*/
protected $accessor;

public function __construct(PropertyNamingStrategyInterface $namingStrategy, AccessorStrategyInterface $accessorStrategy = null)
public function __construct($namingStrategy, AccessorStrategyInterface $accessorStrategy = null)
{
$this->namingStrategy = $namingStrategy;
$this->accessor = $accessorStrategy ?: new DefaultAccessorStrategy();
Expand Down
8 changes: 7 additions & 1 deletion src/JMS/Serializer/GenericDeserializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;

/**
* Generic Deserialization Visitor.
Expand Down Expand Up @@ -160,7 +162,11 @@ public function startVisitingObject(ClassMetadata $metadata, $object, array $typ

public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
{
$name = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$name = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$name = $this->namingStrategy->translateName($metadata);
}

if (null === $data) {
return;
Expand Down
7 changes: 6 additions & 1 deletion src/JMS/Serializer/GenericSerializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use JMS\Serializer\Exception\InvalidArgumentException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;

/**
* @deprecated
Expand Down Expand Up @@ -157,7 +158,11 @@ public function visitProperty(PropertyMetadata $metadata, $data, Context $contex
return;
}

$k = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$k = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$k = $this->namingStrategy->translateName($metadata);
}

if ($metadata->inline) {
if (is_array($v)) {
Expand Down
7 changes: 6 additions & 1 deletion src/JMS/Serializer/JsonSerializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use JMS\Serializer\Exception\InvalidArgumentException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;

class JsonSerializationVisitor extends GenericSerializationVisitor
{
Expand Down Expand Up @@ -164,7 +165,11 @@ public function visitProperty(PropertyMetadata $metadata, $data, Context $contex
return;
}

$k = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$k = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$k = $this->namingStrategy->translateName($metadata);
}

if ($metadata->inline) {
if (is_array($v) || ($v instanceof \ArrayObject)) {
Expand Down
43 changes: 43 additions & 0 deletions src/JMS/Serializer/Naming/AdvancedNamingStrategyInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* Copyright 2016 Johannes M. Schmitt <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace JMS\Serializer\Naming;

use JMS\Serializer\Context;
use JMS\Serializer\Metadata\PropertyMetadata;

/**
* Interface for advanced property naming strategies.
*
* Implementations translate the property name to a serialized name that is
* displayed. It allows advanced strategy thanks to context parameter.
*
* @author Vincent Rasquier <[email protected]>
*/
interface AdvancedNamingStrategyInterface
{
/**
* Translates the name of the property to the serialized version.
*
* @param PropertyMetadata $property
* @param Context $context
*
* @return string
*/
public function getPropertyName(PropertyMetadata $property, Context $context);
}
8 changes: 8 additions & 0 deletions src/JMS/Serializer/SerializerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
use JMS\Serializer\Handler\PhpCollectionHandler;
use JMS\Serializer\Handler\PropelCollectionHandler;
use JMS\Serializer\Handler\StdClassHandler;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
Expand Down Expand Up @@ -205,6 +206,13 @@ public function setPropertyNamingStrategy(PropertyNamingStrategyInterface $prope
return $this;
}

public function setAdvancedNamingStrategy(AdvancedNamingStrategyInterface $advancedNamingStrategy)
{
$this->propertyNamingStrategy = $advancedNamingStrategy;

return $this;
}

public function setSerializationVisitor($format, VisitorInterface $visitor)
{
$this->visitorsAdded = true;
Expand Down
7 changes: 6 additions & 1 deletion src/JMS/Serializer/XmlDeserializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use JMS\Serializer\Exception\XmlErrorException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;

class XmlDeserializationVisitor extends AbstractVisitor implements NullAwareVisitorInterface
{
Expand Down Expand Up @@ -232,7 +233,11 @@ public function startVisitingObject(ClassMetadata $metadata, $object, array $typ

public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
{
$name = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$name = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$name = $this->namingStrategy->translateName($metadata);
}

if (!$metadata->type) {
throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name));
Expand Down
15 changes: 12 additions & 3 deletions src/JMS/Serializer/XmlSerializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;

/**
Expand Down Expand Up @@ -49,7 +50,7 @@ class XmlSerializationVisitor extends AbstractVisitor
/** @var boolean */
private $formatOutput;

public function __construct(PropertyNamingStrategyInterface $namingStrategy, AccessorStrategyInterface $accessorStrategy = null)
public function __construct($namingStrategy, AccessorStrategyInterface $accessorStrategy = null)
{
parent::__construct($namingStrategy, $accessorStrategy);
$this->objectMetadataStack = new \SplStack;
Expand Down Expand Up @@ -244,7 +245,11 @@ public function visitProperty(PropertyMetadata $metadata, $object, Context $cont
if (!$node instanceof \DOMCharacterData) {
throw new RuntimeException(sprintf('Unsupported value for XML attribute for %s. Expected character data, but got %s.', $metadata->name, json_encode($v)));
}
$attributeName = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$attributeName = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$attributeName = $this->namingStrategy->translateName($metadata);
}
$this->setAttributeOnNode($this->currentNode, $attributeName, $node->nodeValue, $metadata->xmlNamespace);

return;
Expand Down Expand Up @@ -293,7 +298,11 @@ public function visitProperty(PropertyMetadata $metadata, $object, Context $cont
}

if ($addEnclosingElement = !$this->isInLineCollection($metadata) && !$metadata->inline) {
$elementName = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$elementName = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$elementName = $this->namingStrategy->translateName($metadata);
}

$namespace = null !== $metadata->xmlNamespace
? $metadata->xmlNamespace
Expand Down
9 changes: 7 additions & 2 deletions src/JMS/Serializer/YamlSerializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use JMS\Serializer\Accessor\AccessorStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\Util\Writer;
use Symfony\Component\Yaml\Inline;
Expand All @@ -40,7 +41,7 @@ class YamlSerializationVisitor extends AbstractVisitor
private $metadataStack;
private $currentMetadata;

public function __construct(PropertyNamingStrategyInterface $namingStrategy, AccessorStrategyInterface $accessorStrategy = null)
public function __construct($namingStrategy, AccessorStrategyInterface $accessorStrategy = null)
{
parent::__construct($namingStrategy, $accessorStrategy);

Expand Down Expand Up @@ -165,7 +166,11 @@ public function visitProperty(PropertyMetadata $metadata, $data, Context $contex
return;
}

$name = $this->namingStrategy->translateName($metadata);
if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
$name = $this->namingStrategy->getPropertyName($metadata, $context);
} else {
$name = $this->namingStrategy->translateName($metadata);
}

if (!$metadata->inline) {
$this->writer
Expand Down
40 changes: 40 additions & 0 deletions tests/Fixtures/ContextualNamingStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/*
* Copyright 2016 Johannes M. Schmitt <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;

/**
* Class ContextualNamingStrategy
*
* Only use this class for testing purpose
*/
class ContextualNamingStrategy implements AdvancedNamingStrategyInterface
{
public function getPropertyName(PropertyMetadata $property, Context $context)
{
if ($context->getDirection() == GraphNavigator::DIRECTION_SERIALIZATION) {
return strtoupper($property->name);
}
return ucfirst($property->name);
}
}
18 changes: 18 additions & 0 deletions tests/SerializerBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Tests\Fixtures\ContextualNamingStrategy;
use JMS\Serializer\Tests\Fixtures\Person;
use JMS\Serializer\Tests\Fixtures\PersonSecret;
use JMS\Serializer\Tests\Fixtures\PersonSecretWithVariables;
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
Expand Down Expand Up @@ -249,6 +251,22 @@ public function testExpressionEngineWhenDeserializing()
$this->assertEquals($person, $object);
}

public function testAdvancedNamingStrategy()
{
$this->builder->setAdvancedNamingStrategy(new ContextualNamingStrategy());
$serializer = $this->builder->build();

$person = new Person();
$person->name = "bar";

$json = $serializer->serialize($person, "json");
$this->assertEquals('{"NAME":"bar"}', $json);

$json = '{"Name": "bar"}';
$person = $serializer->deserialize($json, Person::class, "json");
$this->assertEquals("bar", $person->name);
}

protected function setUp()
{
$this->builder = SerializerBuilder::create();
Expand Down