-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[Serializer] Name Converter #4692
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
Changes from 1 commit
b59b752
4ecc706
24d0320
57e6c94
0442752
d335005
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -162,38 +162,117 @@ needs three parameters: | |
2. The name of the class this information will be decoded to | ||
3. The encoder used to convert that information into an array | ||
|
||
Using Camelized Method Names for Underscored Attributes | ||
------------------------------------------------------- | ||
Converting Property Names when Serializing and Deserializing | ||
------------------------------------------------------------ | ||
|
||
.. versionadded:: 2.3 | ||
The :method:`GetSetMethodNormalizer::setCamelizedAttributes<Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setCamelizedAttributes>` | ||
method was introduced in Symfony 2.3. | ||
.. versionadded:: 2.7 | ||
The :class:`Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface` | ||
interface was introduced in Symfony 2.7. | ||
|
||
Sometimes property names from the serialized content are underscored (e.g. | ||
``first_name``). Normally, these attributes will use get/set methods like | ||
``getFirst_name``, when ``getFirstName`` method is what you really want. To | ||
change that behavior use the | ||
:method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setCamelizedAttributes` | ||
method on the normalizer definition:: | ||
Sometimes serialized attributes must be named differently than PHP class' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the " ' " is wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's to make Even more, since both objects are things and not humans, I think using |
||
properties or getter and setter methods. | ||
|
||
$encoder = new JsonEncoder(); | ||
$normalizer = new GetSetMethodNormalizer(); | ||
$normalizer->setCamelizedAttributes(array('first_name')); | ||
The Serializer Component provides a handy way to translate or map PHP field | ||
names to serialized names: the Name Converter System. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since there is a colon, "The" should be capitialized if I'm correct. |
||
|
||
$serializer = new Serializer(array($normalizer), array($encoder)); | ||
Given you have the following object:: | ||
|
||
namespace Acme; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the namespace is not important here, I'm in favor of removing it |
||
|
||
class Company | ||
{ | ||
public name; | ||
public address; | ||
} | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove one blank line. |
||
And in the serialized form, all attributes must be prefixed by ``org_`` like | ||
the following:: | ||
|
||
{"org_name": "Les-Tilleuls.coop", "org_address": "Euratechnologies, 2 rue Hegel, 59160 Lomme, France"} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's OK to use a real company name and address. What about using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you gimme details for the Acme org (the fake address used)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the following? { "org_name": "Acme Inc.", "org_address": "123 Main Street" } There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use an address in the docs, something like "426 Jordy Lodge, Cartwrightshire, SC 88120-6700" will do (just a random address generated by Faker). Or @javiereguiluz's proposal (which is maybe even better) |
||
|
||
A custom Name Converter can handle such cases:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name converter (lowercased) |
||
|
||
namespace MySerializer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
|
||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface; | ||
|
||
class OrgPrefixNameConverter implements NameConverterInterface | ||
{ | ||
public function normalize($propertyName) | ||
{ | ||
return 'org_'.$propertyName; | ||
} | ||
|
||
public function denormalize($propertyName) | ||
{ | ||
return substr($propertyName, 4) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing semi-colon at the end of the line. I also believe using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that this is more clear, but this is buggy: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, you're correct. Then we should maybe do something like: // remove org_ prefix
return 'org_' === substr($propertyName, 0, 4)
? substr($propertyName, 4)
: $propertyName; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok! |
||
} | ||
} | ||
|
||
The custom normalizer can be used by passing it as second parameter of any | ||
class extending :class:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer`, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I never like using "code names" much in docs. I think just using human language makes things easier to read. If "[...] by passing it as second parameter of any normalizer, including [...]" is correct, I'm in favor of using that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, the name converter system will only work if the custom serializer extends the |
||
including :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` | ||
and :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`:: | ||
|
||
use Acme\Company; | ||
use Symfony\Component\Serializer\Encoder\JsonEncoder | ||
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer; | ||
use Symfony\Component\Serializer\Serializer; | ||
use MySerializer\OrgPrefixNameConverter; | ||
|
||
$nameConverter = new OrgPrefixNameConverter(); | ||
$normalizer = new PropertyNormalizer(null, $nameConverter); | ||
|
||
$serializer = new Serializer(array(new JsonEncoder()), array($normalizer)); | ||
|
||
$obj = new Company(); | ||
$obj->name = 'Les-Tilleuls.coop'; | ||
$obj->address = 'Euratechnologies, 2 rue Hegel, 59160 Lomme, France'; | ||
|
||
$json = $serializer->serialize($obj); | ||
$objCopy = $serializer->deserialize($json); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add some comments showing the result. |
||
|
||
CamelCase to Underscore | ||
~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. versionadded:: 2.7 | ||
The :class:`Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToUnderscoreNameConverter` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing indentation |
||
interface was introduced in Symfony 2.7. | ||
|
||
It's common in many formats to use underscores to separate words. However, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "In many formats, it's common to use underscores to separate words." |
||
PSR-2 specify that the preferred style for PHP properties and methods is | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "specify" should be "specifies" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to be precize, this is located in PSR-1 |
||
CamelCase. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. camelCase (what you're doing with the word camelCase is StudlyCaps) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure about that? https://en.wikipedia.org/wiki/CamelCase (see the Pascal/Microsoft part and the "alternatives" part). In fact, the class currently converts "this_is_a_test" to "thisIsATest" (lower camel case) if you pass the first parameter of its contructor at |
||
|
||
$json = <<<EOT | ||
Symfony provides a built-in Name Converter designed to translate between | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A question for native English speakers: I think that the |
||
underscored and CamelCased styles during serialization and deserialization | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
processes:: | ||
|
||
use Symfony\Component\Serializer\NameConverter\CamelCaseToUnderscoreNameConverter; | ||
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; | ||
|
||
$normalizer = new GetSetMethodNormalizer(null, new CamelCaseToUnderscoreNameConverter()); | ||
|
||
class Person | ||
{ | ||
"name": "foo", | ||
"age": "19", | ||
"first_name": "bar" | ||
private $givenName; | ||
|
||
public function __construct($givenName) | ||
{ | ||
$this->givenName = $givenName; | ||
} | ||
|
||
public function getGivenName() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would prefer firstName to givenName There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer to just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, that will destory the example :) Then I agree with @timglabisch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you guys prefer first name instead of given name? Both Wikipedia and Schema.org use "given name" instead of "first name": There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think "first name" is must more common (at least, for people that are not natives). I didn't even know about "given name" before. It's also what we use in the rest of the docs There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok for consistency. I change it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK "given name" is used mainly in the US while "first name" is the preferred term in UK english. Given name is less ambiguous because in some countries (such as China) the first name (in order of writing) isn't the given name but equivalent to the family name. |
||
{ | ||
return $this->givenName; | ||
} | ||
} | ||
EOT; | ||
|
||
$person = $serializer->deserialize($json, 'Acme\Person', 'json'); | ||
$kevin = new Person('Kévin'); | ||
$normalizer->normalize($kevin); | ||
// ['given_name' => 'Kévin']; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we're still always using the verbose array syntax: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even in a comment? |
||
|
||
As a final result, the deserializer uses the ``first_name`` attribute as if | ||
it were ``firstName`` and uses the ``getFirstName`` and ``setFirstName`` methods. | ||
$anne = $normalizer->denormalize(array('given_name' => 'Anne'), 'Person'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
Serializing Boolean Attributes | ||
------------------------------ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you please add an anchor above this line, to make sure it's BC? (oh dear, doc starts to worry about BC too :(...
.. _using-camelized-method-names-for-underscored-attributes:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the anchor when speaking about snake_case and CamelCase.