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"]:
System.out.println(gson.toJsonTree(Sets.union(
ImmutableSet.of("a"),
ImmutableSet.of("b"))));
But actually, that code prints null, totally unexpected to a user that is not familiar with the implementation of Sets.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:
gson.toJsonTree(union, TypeToken<Set<String>>(){}.getType());.
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:
ImmutableMap.of(
"key1", Sets.union(...),
"key2", new HashSet(){},
"key3", new MyRecord(){}
);
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).
Very early versions of Gson actually supported inner classes.
What do you expect to happen to the outer class reference? Ignore it silently or serialize it as well?
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:
Fields corresponding to the outer classes in inner classes, anonymous classes, and local classes are ignored and not included in serialization or deserialization.
If you don't want to implement this, fine, but at least give an exception instead of silently serializing to null. I just lost way too much time debugging some weird NullPointerExceptions until I realized it was due to the use of anonymous classes.
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 toJson(obj, withAnonymousStuff = true).
Most helpful comment
If you don't want to implement this, fine, but at least give an exception instead of silently serializing to
null. I just lost way too much time debugging some weirdNullPointerExceptions until I realized it was due to the use of anonymous classes.I think deserialization should be possible as an opt-in through the use of custom type adapters.