20.
Taking Control of the Serializer
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
Whoops, an error! Please, try again later.
22 Comments
Did she just say, "and wait impatiently?"
Ha!
Hi, how could we implement the ExclusionPolicy with FOSUserBundle ? I can't "hide" in the serialization, the password, salt etc... :'(
Great question actually! Try this out and let me know what you find: https://github.com/schmittj...
Cheers!
Hi :) Thanks for the answer. Well i've just made this after my question and that's correct, it's works :)
Thank's you for the screencast !
Hi,
Having trouble getting the User entity serialized with exclusion policy. We extend it from FOSUserBundle, desopite saying ExclusionPolicy(all), all fields are serialized. Its as if JMS serializer is ignoring annotations. I searched the web and found config changes to be done for FOSUserBundle entity, I implemented those, but no change. Only thing that seems to be working is by configuring groups and setting them in the context. JMS even exposed a FK collection I defined under a different group. So, if you do not set a group, all other annotations are simply ignored! I am using Symfony 3.4 and JMS bundle: 2.3.
I changed things as per this: http://bit.ly/2mEZwBw And http://bit.ly/2DwcOrp
/**
* @Serializer\ExclusionPolicy("all")
*/
class Therapist extends User
{
/**
* @Serializer\Expose()
* @Serializer\Groups("{Deep}")
*/
private $clinics;
}
Despite configuring "deep" group above, if I do not set group, JMS also exposes this property. Am I doing something wrong ?
Hey Mrugendra Bhure!
Oh boy, this is a mess! JMSSerializer does not play well when you extend a base class: it seems that, under normal situations, *you* can only control the serialization rules for the fields in *your* class, not the parent class.
It's clear to me from looking around that, for some reason, the fix for this will involve you using YAML serialization rules instead of annotations: Check out this thread for details: https://github.com/schmittj...
And honestly, due to all this craziness, you could also decide to NOT use the serializer for just this one object, and instead turn it into JSON manually (or, turn it into an array and the put that through the serializer, which should allow embedded objects [if you want them in your JSON] to still be serialized through JMS).
I hope that helps! Cheers!
Hi Ryan,
When you make updates to courses, how do I know what's been updated?
I've finished some of the courses, but periodically see "Updated 3 days ago", or so, don't see any new videos, so don't know what's been updated.
Thank you!
Hey Vlad!
This is something we're still working on - right now the "Updated" status (unless a course is being actively released still) usually is not significant (we probably tweaked something insignificant). We plan to publish an actual "changelog" whenever we make significant changes in the future. It's on the list!
Cheers!
Thanks, Ryan!
I'm guessing there didn't make the "Hey Serializer" graphic/meme.
hahaha, I can bet Leanna has the credit on that
Cheers!
I notice that you always use the Annotation way, I'm trying to avoid in order to use configuration files in yml, I think that way is more decoupled from the framework or tool, but I don't really know for sure, can you tell me why are you using Annotations?
Hi Roberto!
Yes, very fair question :). First, there is no performance difference or flexibility between the formats. So, it *does* come down to developer preference. I like annotations because I like having my configuration right next to the thing it's configuring. For serializing, you can immediately see what properties are being serialized, without needing to find another configuration file. Route & Doctrine annotations also have that same advantage.
About the coupling idea, I tend to think that idea is over-hyped. You *are* using Symfony, and it's massively unlikely that you'll need to switch suddenly to using something else. And even if you *did* need this, having your configuration in YAML instead of annotations won't make much difference - it would be pretty easy to quickly delete the annotations from your class if you decided to use a different library for serializing. Decoupling from your framework is really important if you're sharing your code (you don't want to force your serialization configuration on another use, just so they can use your class) - but purposefully *coupling* your code to your framework - along with use a nice layer of services, that's key - is a great way to be pragmatic and stay productive. That's subjective of course - but that at least shows you why I've made these choices :).
Cheers!
Hey Ryan
It is me again ;)
I try to use the Symfony's serializer and use the Groups for handling the response.
I tried this:
protected function serialize($data)
{
$encoders = [new XmlEncoder(), new JsonEncoder()];
$normalizer = new ObjectNormalizer();
$serializer = new Serializer([$normalizer], $encoders);
return $serializer->serialize($data, 'json', ['groups' => ['group1']]);
}
And in my model I put the @Groups({"group1"})
But as you can imagine it doesn't work ;)
If I put $normalizer->setIgnoredAttributes(['user', 'id']); it is ok I don't have the user and id but in the doc it write is better to user the annotation instead the ignoredAttributes.
Do you know what is my mistake ?
Thanks again for your work
Hi Greg!
I might know the issue :). Obviously, as you found out, there is a Serializer component in Symfony, which means you can create a Serializer object from scratch, adding in whatever normalizers, encoders, etc that you want. But, when you use the Symfony Framework, we do this for you. As soon as you uncomment this line (https://github.com/symfony/symfony-standard/blob/bba96b98623851b0ce9331c6fbe9ab2b7e57ae27/app/config/config.yml#L21), you will have a
serializerservice... which means you can just do:Now, your approach should also work, but I think you're missing the extra setup needed to tell the Serializer to read the annotations. Check out this section: http://symfony.com/doc/current/components/serializer.html#attributes-groups
So, you're totally free to keep creating the Serializer yourself - but you may not need to! But if you do continue to do this, just make sure to make the tweaks in that section so that your annotations are loaded :).
Cheers!
Hi Ryan,
Exactly I definitely forgot to initialize the ClassMetadataFactory.
So I just need to initialize it just above ?
Thanks
You got it :). The 4th code block on that link shows everything all put together - that ClassMetadataFactory is passed to your ObjectNormalizer.
Have fun!
Thanks again I'am so stupid that I didn't see it in the example :)
Btw Nice tuto about ES6.
You mention at the end of this tutorial that you prefer to use forms instead of the Serializer to turn the json back into an object. Can you elaborate on why you prefer to use the form method over the serializer?
Hey Tom!
Definitely - good question :). There are a few reasons:
1) Data transformers - the idea that your user might send you an "id", but on your object, that property is itself an object. The EntityType is built to do this type of transformation
2) Similar to the above, I find that your output doesn't always match your *input*. I mean, if I literally looked at the JSON for a GET /blog/{id} endpoint and compared it with the JSON that I send to *create* a blog post, they will differ more than you might think. So, at first, it seems kind of awesome to have one model class that you can serialize for output and deserialize for input. But in reality, it's not often that simple, and the form gives you that layer to hide/show fields or add other transformations.
If I summarize these two reasons, it comes down to this: the serializer is "stupid" by design: it simply takes the JSON (when deserializing) and puts it onto an object. Unless that JSON and your object match perfectly, it gets tough. On the other hand, we going from your model to JSON is often easier: we typically design our model classes to match the JSON we want with little or no effort.
But, not everyone agrees - that's why the deserializer exists! But I like having a model class that models my output, and a form class that models my input.
Cheers!
Hey! Thanks a lot for this, you guys are doing one hell of a job.. I didn't go through the hole code, but it showed me some tricks that were really useful.
Hey Matias,
There're a lot of tricks in REST ;) We are really glad you like this course and it's helpful for you!
Cheers!
"Houston: no signs of life"
Start the conversation!