-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Allow serialization of anonymous classes #1510
Comments
Very early versions of Gson actually supported inner classes. |
Note that the topic of this issue is not inner classes but anonymous classes. Anyway, ignoring the references to the outer class seems fine (imagine a circular dependency otherwise). Gson's documentation already explicitly mentions the behaviour to fields corresponding to outer classes:
|
If you don't want to implement this, fine, but at least give an exception instead of silently serializing to I think deserialization should be possible as an opt-in through the use of custom type adapters. |
There should be some option to tell Gson to include the fields of anonymous classes, something like |
Besides general support for serialization of anonymous classes, there are also these special cases for which it would be even more reasonable to allow serialization or deserialization:
Personally, I find the proposal mentioned in #1510 (comment) to throw an exception on deserialization quite compelling, but I think it can unfortunately not be easily implemented:
Also, on deserialization trying to detect whether a local or anonymous class uses the enclosing instance does not seem to be possible (until recently, see JDK-8271623), because even when the enclosing instance is not used, the compiler seems to generate a field storing the enclosing instance anyways. So maybe Gson should just remove restriction for local and anonymous classes, assuming that the users knows what they are doing. This would be backward incompatible, but the question is how many users really rely on Gson ignoring the values for anonymous and local classes. Users could still achieve the old behavior by specifying an @eamonnmcmanus, what do you think about dropping this restriction for anonymous and local classes? |
I'm not terribly motivated to support serializing anonymous classes. It's easy enough to make a named class if you need to serialize it, and I'm concerned that the serialization could turn out to be a can of worms. I'm more sympathetic to the notion of throwing an exception rather than serializing |
That might not even be necessary, they can probably just register an |
Thanks for PR #2189! That enabled me to see the effect of throwing an exception here, by running the change against all of Google's internal tests. (We have thousands of non-test source files that reference the Gson API.) I found one place where a field with this anonymous The main alternative seems to be to support serializing anonymous classes in at least some cases, as alluded to by @Marcono1234 above. I'm afraid that would also cause similar problems, though, unless we introduced yet another We have seen a number of cases like this where we want to do the right thing but are hampered by the risk of breaking existing users. I am wondering if we should maybe introduce the notion of a "compatibility level". It might be an enum, with constants like |
This also highlights other flaws with the current behavior:
I guess that would be possible, but I am a bit afraid that this could turn into a maintainability and troubleshooting nightmare. The effect of the current |
Its interesting to see why the decision to not serialize anonymous classes was taken in the first place. As many others I just found this issue indirectly, when I used It happened that my claims contained Set<String> filteredScopes = Sets.intersection(requestedScopes, allowedScopes); As soon as I added the result to a new The main problem I see here is that the serialization result depends on the conditions not always controllable by a calling party. E.g. I didn't know until now that the result of The fact that when collection implementation is not supported, this error is silently ignored, was also surprising, but I don't think this problem should be solved by changing the behavior to throwing an exception. I think the solution should be to allow serialization of any implementation of supported interfaces by default. It could be considered as a breaking change, but here we are returning to my first question: why the decision to not serialize anonymous classes was taken in the first place? Is it really a deliberate decision or just overlooking? Are there any reason for people to rely on this specific behavior? If not, then this breaking change will only "break" some very rare cases anyway and I would rather consider it as a "bug fix". |
The comment from @xak2000 is interesting. We probably want to continue not trying to serialize anonymous classes via reflection. But in cases where another |
Describe the feature
Gson should allow serialization of anonymous classes, the reason is that the user shouldn't care about the implementation of the code that generates the objects they are using.
For example, this code that only uses Guava and Gson looks fine and users may expect it to print
["a", "b"]
:But actually, that code prints
null
, totally unexpected to a user that is not familiar with the implementation ofSets.union
(that function returns an instance of an anonymous class).Additional context
I think this feature is well deserved because of the amount of confusion that has been around the lack of it. If we do a Google search we find several people who were caught by this issue:
And the list goes on and on.
I think what aggravates the lack of this feature it he way Gson silently serializes those instances to
null
, which is a source of silent bugs.NOTE:
Deserialization of anonymous inner classes is problematic, I'm not asking for that to be supported. This feature request deals only with serialization.
Possible workarounds
I've seen suggested workarounds like:
But notice that only works in the most simple of cases, but it doesn't work in cases where we have a Map with values of different anonymous classes:
As there is not a single TokenType I can accommodate for that disparity of values and that will behave as expected. Moreover, sometimes the values are not known at compile time (in designing APIs, the values can be anything the user passes to us, and its out of our control).
The text was updated successfully, but these errors were encountered: