-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] Injecting additional data during serialization #18904
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
Comments
What about serializing view/value objects instead? Imo it's not the best idea to expose your internal structure to the outside world. If you treat your entity as a simple typed array, why not just serialize an array? |
Why not creating your own normalizer in which you could inject the router ? |
@ogizanagi is right, creating a custom normalizer is the way to go (it's what we do in API Platform: https://github.com/api-platform/core/blob/master/src/JsonLd/Serializer/ItemNormalizer.php) |
@ogizanagi @dunglas I think @iltar's recommendation of creating serializable view objects is the most flexible, but I'm wrestling with a tradeoff of convenience. For example, let's pretend I have a Case entity object with associated Customer and many CaseItems, and I'm building a report that needs:
For this single use-case, I need:
That gives the consumer access to:
Am I off base? Over-complicating it? If so, how? It seems clean, but not very convenient when I could instead just use serializer groups on the entities and (if I had my way) build a couple simple listeners that append the URL to the normalized data when Customer or CaseItem are being normalized in a certain context. |
@simshaun: This is not over-complicating it: we're quite doing the same thing in a "pseudo-DDD" approach in our application for any data we pass to our templates. We build DTO objects called "Views" and assembled by an "Assembler".
Create your normalizer with a custom format. (Not just You can also use the |
Finally revisiting this...
That seems hacky (not really an intended use of
The problem I have with this is that the context would need to know about every serialization use-case. |
It is, Your use case is relatively specific. If may require a bit of tinkering and customization on top of the Symfony Serializer, but I don't think it's something that should be done in the Serializer core. |
You're right. But, the process of normalization is just about transforming complex data (objects) into simpler data (array & scalars). This transformation may lead to different representations according to your use case. Those representations can easily be identified through the format specified when normalizing your data. I do think it's the most straightforward usage in an application. But fine, if you don't want to use the format, use the context. Simply register a normalizer supporting your object class and the expected format (json for instance). Then, inject a map of sub-normalizers (as value) to handle the normalization according to the use case (the key) specified into the context. Otherwise, you can still assemble the expected data in a view DTO first, and serialize it directly (yes, again, it needs more work, but it also brings visibility). |
Also #19371 would simplify this by allowing you to create directly one normalizer per use case, by accessing the |
I disagree. I think it's fairly common (at least in everything I've done in the past few years) to want to add additional data, like URLs, when an object is being serialized. View objects/DTOs solve the problem, but they're not very convenient to create when I've got a tree that's several levels deep and some of the entities have quite a few properties. What I've done in the meantime is create a custom normalizer that calls a couple user-defined callbacks from the $context array.
I don't know if that's good or bad, but it works. |
Hey there. Using I can't use the approach of @simshaun because the serialization in my case is done internally be the "algolia-bundle" |
Not sure why you get this circular ref here without looking at your code. But try injecting the doctrine manager registry instead |
Ah, thanks @ogizanagi that does the trick. |
Still can't add value and properties extras? |
@chiqui3d anything concrete to add? Like a use case and what you would like to see? |
Yes @theofidry, for each object I want to create a link/path like property in the serialization based on the entity ID, thanks |
You can already do that easily with a custom format or normalizer as per the conversation above |
Sorry for delay @theofidry Okay, I just realized that in the entity I can create a virtual getter for the URL and access the data. This is easier than creating a custom normalizer. btw, I don't understand is when I create a calback for a particular field, I can't access the others values only own value :( |
Thank you for this suggestion. |
Friendly reminder that this issue exists. If I don't hear anything I'll close this. |
Hey, I didn't hear anything so I'm going to close it. Feel free to comment if this is still relevant, I can always reopen! |
I frequently have serialization use cases where the frontend needs more information about each entity than is available in the entities themselves. Just one example is using the router to provide URLs for each entry when serializing a collection.
From what I can see, there doesn't appear to be an easy way to do that. I propose allowing the optional use of an event dispatcher during the normalization process to modify the data that gets encoded.
The text was updated successfully, but these errors were encountered: