Skip to content
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

Support serializing anonymous and local class with custom adapter #2498

Conversation

Marcono1234
Copy link
Collaborator

@Marcono1234 Marcono1234 commented Sep 23, 2023

Purpose

Resolves #1510
(but only for the cases where a custom adapter exists for the class; not if the reflection-based adapter would be used)

Description

When serializing an anonymous or local class for which a custom adapter exists (i.e. not the reflection-based adapter), it will now use that adapter instead of serializing null.
Deserialization is still not supported, even if a custom adapter exists, because some custom adapters like the built-in Collection adapter might fall back to using JDK Unsafe to create an instance, and that might lead to runtime exceptions then due to uninitialized fields. Also, for deserialization this issue most likely can only occur for local classes, and can be worked around by making the class non-local.

Future topics:

  • Should reflection-based serialization be possible since it ignores synthetic fields by default?
    (And are there possibly cases where a field is compiler-generated but not marked as synthetic?)
  • Should deserialization be possible if a custom adapter exists?
    (The main issue here is making sure JDK Unsafe is not used to create an instance of such a class, to avoid ending up with uninitialized fields.)

I am not planning to submit any pull requests for these future topics yet. It might be better if we first see which of these features the users actually need, and if these use cases are common.

Checklist

  • New code follows the Google Java Style Guide
  • If necessary, new public API validates arguments, for example rejects null
  • New public API has Javadoc
    • Javadoc uses @since $next-version$
      ($next-version$ is a special placeholder which is automatically replaced during release)
  • If necessary, new unit tests have been added
    • Assertions in unit tests use Truth, see existing tests
    • No JUnit 3 features are used (such as extending class TestCase)
    • If this pull request fixes a bug, a new test was added for a situation which failed previously and is now fixed
  • mvn clean verify javadoc:jar passes without errors

}

if (isAnonymousOrNonStaticLocal(field.getType())) {
if (excludeClass(field.getType(), serialize)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this to avoid code duplication. This should be identical to the previous behavior, but previously excludeClass was called separately:

private boolean includeField(Field f, boolean serialize) {
return !excluder.excludeClass(f.getType(), serialize) && !excluder.excludeField(f, serialize);
}

(and it looks like there are no other callers of excludeField)

Comment on lines 144 to 148
assertThat(EnumSet.allOf(Roshambo.class)).isEqualTo(
gson.fromJson("[\"123ROCK\",\"123PAPER\",\"123SCISSORS\"]", new TypeToken<Set<Roshambo>>() {}.getType())
);
Set<Roshambo> deserialized = gson.fromJson("[\"123ROCK\",\"123PAPER\",\"123SCISSORS\"]", new TypeToken<Set<Roshambo>>() {}.getType());
assertThat(deserialized).isEqualTo(EnumSet.allOf(Roshambo.class));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this because previously "actual" and "expected" were switched.

@Marcono1234
Copy link
Collaborator Author

@eamonnmcmanus, I hope that is what you had in mind. But, in case you are not planning to do so anyway, could you please run this against the Google projects to see if there are any unintended side-effects?

@Marcono1234 Marcono1234 mentioned this pull request Nov 18, 2023
9 tasks
…tion

# Conflicts:
#	gson/src/main/java/com/google/gson/internal/Excluder.java
#	gson/src/test/java/com/google/gson/functional/EnumTest.java
#	gson/src/test/java/com/google/gson/functional/ObjectTest.java
@Marcono1234 Marcono1234 force-pushed the marcono1234/anonymous-local-custom-serialization branch from 915ce56 to fdc1a76 Compare November 19, 2023 15:30
@eamonnmcmanus eamonnmcmanus self-requested a review November 19, 2023 23:38
@eamonnmcmanus
Copy link
Member

Sorry about the delay. I've run this against Google's tests and everything passed, except a couple of tests that were explicitly testing for the current behaviour. I doubt that that's critical, but will investigate further.

Copy link
Member

@eamonnmcmanus eamonnmcmanus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for doing this!

@eamonnmcmanus eamonnmcmanus merged commit 46ab704 into google:main Jan 29, 2024
11 checks passed
@Marcono1234 Marcono1234 deleted the marcono1234/anonymous-local-custom-serialization branch January 30, 2024 22:13
tibor-universe pushed a commit to getuniverse/gson that referenced this pull request Sep 14, 2024
…ogle#2498)

* Support serializing anonymous and local class with custom adapter

* Fix formatting and fix switched 'expected' and 'actual' in EnumTest

* Minor code improvements

---------

Co-authored-by: Éamonn McManus <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow serialization of anonymous classes
2 participants