serializer: SerializedName ignored when using IdenticalPropertyNamingStrategy

It appears as though the @SerializedName annotation is being ignored, when used with the IdenticalPropertyNamingStrategy.

My user class

// MyApp\Model\User

namespace MyApp\Model;

use JMS\Serializer\Annotation as JMS;

/**
 * User
 */
class User {
  /**
   * @var integer
   *
   * @JMS\SerializedName("foo")
   */
  private $someProp;

  // ...
}

Instantiating the serializer (I’m using ZF2, so this is a service factory)

return array(
  // ...
  'service_manager' => array(
    'factories' => array(
      'jms_serializer' => function() {
        \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
          'JMS\Serializer\Annotation',
          __DIR__ . '/../../../vendor/jms/serializer/src'
        );

        $namingStrategy = new \JMS\Serializer\Naming\IdenticalPropertyNamingStrategy();
        return \JMS\Serializer\SerializerBuilder::create()
          ->setCacheDir(__DIR__ . '/../../../data/cache')
          ->setPropertyNamingStrategy($namingStrategy)
          ->build();
      }
    )
  )
);

With this setup, the User object is being serialized a { "someProp": "someValue" }. I would expect it to be serialized as { "foo": "someValue" }

I believe the issue is within the JMS\Serializer\Naming\IdenticalPropertyNamingStrategy:

class IdenticalPropertyNamingStrategy implements PropertyNamingStrategyInterface
{
    public function translateName(PropertyMetadata $property)
    {
        return $property->name;
    }
}

If I override the translateName method to check for a serializedName property, my issue is fixed.

       public function translateName(PropertyMetadata $property) {
        if ($property->serializedName) {
            return $property->serializedName;
        }
        return $property->name;
    }

I can submit a pull request to fix this – I just want to check that I’m going about this the right way, first.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Reactions: 4
  • Comments: 18 (3 by maintainers)

Commits related to this issue

Most upvoted comments

My solutions is:

services:
    jms_serializer.camel_case_naming_strategy:
        class: 'JMS\Serializer\Naming\IdenticalPropertyNamingStrategy'

as SerializedNameAnnotationStrategy is used by default, but a fallback it has is CamelCaseNamingStrategy which for some reason does not camel case column names. Now IdenticalPropertyNamingStrategy becomes the fallback and it works is SerializedName annotation is not present.

Edit: In the current version IdenticalPropertyNamingStrategy can be set in the config::

jms_serializer:
    property_naming:
        id: jms_serializer.identical_property_naming_strategy

Try this:

$serializer = \JMS\Serializer\SerializerBuilder::create()
    ->setPropertyNamingStrategy(
        new SerializedNameAnnotationStrategy(
            new IdenticalPropertyNamingStrategy()
        )
    )
    ->build();

So I’m setting the property naming strategy to SerializedNameAnnotationStrategy() with IdenticalPropertyNamingStrategy() as a property naming strategy delegate for properties without the @SerializedName annotation.

I found the same issue!

My solution was to replace the name strategy with a compiler pass to my own strategy which is:

class IdenticalPropertyNamingStrategy implements PropertyNamingStrategyInterface
{
    public function translateName(PropertyMetadata $property)
    {
        return $property->serializedName ?: $property->name;
    }
}

This was also not what I expected. To make this work, I just created another naming strategy:

<?php

namespace SmartestK12\JMSSerializerNamingStrategies\Naming;

use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\Metadata\PropertyMetadata;

class IdenticalUnlessSpecifiedPropertyNamingStrategy implements PropertyNamingStrategyInterface
{
    public function translateName(PropertyMetadata $property)
    {
        $name = $property->serializedName;

        if (null !== $name) {
            return $name;
        }

        return $property->name;
    }
}

This could be a simple 3 line change to the existing IdenticalPropertyNamingStrategy, but would be a backwards compatibility break (in the case that someone was using this naming strategy and had a SerializedName annotation specified).

I’d be more than happy to provide a pull request with tests for this if desired, but presume that a better approach may be to create another naming strategy similar to this IdenticalUnlessSpecifiedPropertyNamingStrategy instead of modifying the existing one.

Let me know if you’d like any contributions here (otherwise it might be safe to close this issue).

I encounter the exact same issue. I agree with the solution: @SerializedName should override the naming strategy.

A solution for this should be created indeed. It’s a nasty one to stumble upon and figure out.

Steps to fix for those coming after me:

  • added @m14t’s IdenticalUnlessSpecified strategy to my project
  • change config.yml parameters:

jms_serializer.serialized_name_annotation_strategy.class: My\Name\Space\Serializer\IdenticalUnlessSpecifiedPropertyNamingStrategy