-
Notifications
You must be signed in to change notification settings - Fork 22
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
fix(serialization): incorrect map serialization #139
Conversation
When switching to Symfony's serializer, the MapDenormalizer was implemented, but not added to the Serializer parameters. Thus, the attributes of a realm and other fields using the Map type were always empty. Additionally, the MapNormalizerTest contained test data for the denormalizer. We adjusted this to correctly ingest Map's as the test values. To properly normalize the Map type, we made the inner array publicly accessible. Previously the ArrayObject would otherwise hold an array with the entire Map object wrapped by the Map classname. This was addressed, by directly accessing the inner array and passing it to the ArrayObject. We also added an integration test to prevent these kind of issues in the future, and to test the update method for realm attributes. (cherry picked from commit b5bffe8)
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #139 +/- ##
=======================================
Coverage 99.20% 99.20%
=======================================
Files 26 26
Lines 756 756
=======================================
Hits 750 750
Misses 6 6 ☔ View full report in Codecov by Sentry. |
Thanks a lot for your PR 🙏 Looks good to me, the only thing I'm not exactly sure is whether we should expose the |
Always happy to give something back. Well to be honest id prefer to remove the map type entirely. But i don't know that much about the usage so you can judge that with more background. I don't think there is any issue with it as it is also marked readonly and already accessible via the json method just converted to an object. Currently it is also rather hard DX wise to alter attributes, because they are contained in the Map. And we would need to access the array to create a new Map with the existing entries of an existing Map to alter the content. But im open for suggestions and your input here. |
I think the reason for the map to exist is because I wanted to stay as close to the types used in Keycloak itself - a I also intended to go the "objects are immutable" way, but I see how this degrades DX for using maps in this library 😅 I didn't quite make up my mind right now about the Do you mind if we for now just fix the missing Thanks for the discussion, I very much appreciate it! |
Ah sure we can discuss this first. I need to verify again tomorrow if this works without the access to the array but i think it was necessary to do so because the serialization result had the inner array wrapped behind the class name as a key when throwing in the map type into the serializer. Ill get back to you tomorrow 🙌 |
Okay, we somehow need access to the underlying map array, otherwise as i said, the serialization will encapsulate the data wrapped in the "map" attribute: See this test output for example:
In the next iteration, we also should consider not tagging the Map as |
Thank you for all your efforts with this issue! I'm super hesitant to break the consistency with the rest of the code by changing the Looking at the WDYT about adding the necessary modifier methods to the // other methods like e.g. ::has(string $key) or ::get(string $key)
// as well as some ::toArray() maybe
public function with(string $key, $value): self
{
$clone = clone $this;
$clone->map[$key] = $value;
return $clone;
}
public function without(string $key): self
{
$clone = clone $this;
unset($clone->map[$key]);
return $clone;
} This keeps the immutability aspect and follows the pattern of how other parts of the library are designed and implemented. I'll create new branch off of yours trying to implement these bits 😄 |
Oh sure it is your project, I'm just giving you my opinion here and i can understand why you do not want to do this. Though i think this whole thing feels like following an ideology just for the sake of consistency / alignment with Keycloak's Java code. For now, i think your suggested improvements are a good solution for the current issue and I'd love to discuss future ideas at any time :) Coming back to this PR though: What is your proposed solution to the Map type that i should go for in this PR to make it merge-able? Thanks for your timely answers its great to discuss such changes! |
With consistency I was referring to how the representations are implemented because their properties are also encapsulated and they are immutable 😄It would break consistency with the existing DX, not with Java's types. If PHP would allow some kind of generics, the I've picked your commit and made adjustments in #140. If the changes to the |
Sounds reasonable and thanks for maintaining this library! The changes in your PR look good to me! Thanks again 🫶 |
Thank you too! I merged and released v0.28.0 🎉 It didn't recognize your commit was included, but I mentioned you in the release notes 😊 |
When switching to Symfony's serializer, the MapDenormalizer was implemented, but not added to the Serializer parameters. Thus, the attributes of a realm and other fields using the Map type were always empty.
Additionally, the MapNormalizerTest contained test data for the denormalizer. We adjusted this to correctly ingest Map's as the test values.
To properly normalize the Map type, we made the inner array publicly accessible. Previously the ArrayObject would otherwise hold an array with the entire Map object wrapped by the Map classname. This was addressed, by directly accessing the inner array and passing it to the ArrayObject.
We also added an integration test to prevent these kind of issues in the future, and to test the update method for realm attributes.