-
Notifications
You must be signed in to change notification settings - Fork 228
Arraylist<LayoutBlock> GSON anonymous inner class initialization bug #1004
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
Conversation
GSON has a known issue where null is returned if it tries to serialize a list of object that was initialized using an anonymous inner class. This commit tried to patch this.
Codecov Report
@@ Coverage Diff @@
## main #1004 +/- ##
============================================
- Coverage 76.77% 76.69% -0.09%
- Complexity 3685 3688 +3
============================================
Files 403 403
Lines 11111 11120 +9
Branches 1108 1111 +3
============================================
- Hits 8530 8528 -2
- Misses 1907 1921 +14
+ Partials 674 671 -3
Continue to review full report at Codecov.
|
filmaj
left a comment
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.
LGTM, but will defer to @seratch for approval
| } | ||
| } | ||
|
|
||
| private static String getJsonWithGsonAnonymInnerClassHandling(List<LayoutBlock> blocks){ |
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'd add a comment here that explains why we need this method, just as a hint to a maintainer reading through this code in the future (I have a bad memory so I probably won't remember the details of this problem in 6 months!). Maybe just a quick link to the GSON issue and a single sentence explanation.
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.
Sounds good. Adding a link to the gson project issue would be easier.
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.
Agreed, I added a comment with the link to the original issue
|
|
||
| @Test | ||
| public void testGetJsonWithGsonAnonymInnerClassHandling() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { | ||
| // SETUP |
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 like the test structure. If you want to have these comments, probably Given-When-Then style would be more common.
| } | ||
| } | ||
|
|
||
| private static String getJsonWithGsonAnonymInnerClassHandling(List<LayoutBlock> blocks){ |
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.
Sounds good. Adding a link to the gson project issue would be easier.
| @Test | ||
| public void testGetJsonWithGsonAnonymInnerClassHandling() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { | ||
| // SETUP | ||
| Method method = RequestFormBuilder.class.getDeclaredMethod("getJsonWithGsonAnonymInnerClassHandling", List.class); |
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.
You can test one of the public methods that internally calls getJsonWithGsonAnonymInnerClassHandling instead of trying to run the private method using reflection APIs.
| form.add("blocks", req.getBlocksAsString()); | ||
| } else if (req.getBlocks() != null) { | ||
| String json = GSON.toJson(req.getBlocks()); | ||
| String json = getJsonWithGsonAnonymInnerClassHandling(req.getBlocks()); |
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.
req.getUsers(): List<String> patterns also need the same workaround.
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.
Makes sense, I also noticed that the Map objects also suffered from this GSON issue, I added additional code to handle these use cases.
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.
Good catch! Thanks
Took feedback from PR and added support for Map object which suffer from the same GSON issue
seratch
left a comment
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.
Great improvement 💯 Thanks for fixing this!
| form.add("blocks", req.getBlocksAsString()); | ||
| } else if (req.getBlocks() != null) { | ||
| String json = GSON.toJson(req.getBlocks()); | ||
| String json = getJsonWithGsonAnonymInnerClassHandling(req.getBlocks()); |
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.
Good catch! Thanks
|
|
||
| @Test | ||
| public void testEmptyListJsonSerialization() { | ||
| // GIVEN |
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.
As far as I know, using all capital letters for the Given/When/Then labels is not a common style but it's a minor thing. I will merge this as-is this time. See also: https://dzone.com/articles/a-new-approach-to-given-when-then
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 was using this pattern based on an article I read a long time ago, I did not know this was well known pattern. Thanks!
GSON has a known issue where null is returned if it tries to serialize an object that was initialized using an anonymous inner class.
Example:
The above assertion should be true but the json string generated by the GSON lib actually returns a string of value "null". This can lead to some head scratching for the users of this library.
These changes try to reinitialize & reserialize the list of blocks if this "null" output is obtained from the GSON library.
Category (place an
xin each of the[ ])Requirements
Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to the those rules.