-
Notifications
You must be signed in to change notification settings - Fork 459
feat: GsonFactory to have read leniency option #1819
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
fbde6d2
to
8528bdb
Compare
8528bdb
to
5ad553b
Compare
lint (non required) fails:
This is irrelevant to this pull request. |
google-http-client-gson/src/main/java/com/google/api/client/json/gson/GsonFactory.java
Outdated
Show resolved
Hide resolved
return readLeniency; | ||
} | ||
|
||
private static GsonFactory newInstance(GsonFactory gsonFactory) { |
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 per Effective Java's clone section, creating a factory method. I don't think a subclass needs to access this method.
|
||
/** Returns a copy of GsonFactory instance which is lenient when reading JSON value. */ | ||
public GsonFactory withReadLeniency() { | ||
GsonFactory copy = newInstance(this); |
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.
If we're supporting the subclassing use-case, I don't see how this works. Is the intent that subclasses are required to override this function? (If so, we're introducing a backwardly incompatible change to the subclass contract.)
As an example:
// Logs all method invocations.
public class LoggingGsonFactory extends GsonFactory { /* ... */ }
// In some 'main'-type class of the application...
public static GsonFactory createGsonFactory() { return new LoggingGsonFactory(); }
// Then elsewhere...
private GsonFactory gsonFactory = createGsonFactory().withReadLeniency();
// Oops! No more logging.
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 point. Then subclasses needs to override newInstance. I'm making newInstance protected.
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.
But now it's static.
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.
Consider avoiding the copy problem altogether.
private boolean isLenient;
public GsonFactory() { this(false); }
public GsonFactory(boolean isLenient) { this.isLenient = isLenient; }
// No withReadLeniency() method.
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.
The boolean flag in the constructor is not good (Avoid boolean parameter go/java-practices/boolean-parameters). It's ambiguous, especially when we want to introduce leniency in writing JSON.
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.
Added * <p>Subclasses should not call this method. Set {@code readLeniency} field to {@code true} instead.
.
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.
"Subclasses should not call this method" is fine if you know you're dealing with a subclass. The point of polymorphism is that you shouldn't care.
There's other ways to take in a setting besides using a boolean if you feel it goes against best practices.
public enum Leniency {
LENIENT, STRICT
}
private final Leniency leniency;
public GsonFactory() { this(Leniency.STRICT); }
public GsonFactory(Leniency leniency) { this.leniency = Objects.requireNonNull(leniency); }
or a Builder, or a Settings object parameter.
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 talked, we may want to add more parameters (such as writeLeniency) in future and having different contstructors for different parameter is not good.
I'm bringing Builder 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.
@burkedavison PTAL.
|
||
/** Returns a copy of GsonFactory instance which is lenient when reading JSON value. */ | ||
public GsonFactory withReadLeniency() { | ||
GsonFactory copy = newInstance(this); |
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.
Added * <p>Subclasses should not call this method. Set {@code readLeniency} field to {@code true} instead.
.
|
||
public final void testReaderLeniency_lenient() throws IOException { | ||
JsonObjectParser parser = | ||
new JsonObjectParser(GsonFactory.builder().setReadLeniency(true).build()); |
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.
Memo: This is how to create GsonFactory with readLeniency true.
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.
@burkedavison PTAL.
cfbeec9
to
11d7165
Compare
|
||
public class GsonParserTest extends AbstractJsonParserTest { | ||
|
||
@Override | ||
protected JsonFactory newJsonFactory() { | ||
return new GsonFactory(); | ||
} | ||
|
||
public void testParse_leniency() throws IOException { |
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.
This wasn't supposed to come here.
This also changes the JDK distribution from zulu to temurin https://github.com/actions/setup-java#eclipse-temurin Source-Link: googleapis/synthtool@ef9fe2e Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:31c8276a1bfb43766597d32645721c029cb94571f1b8d996cb2c290744fe52f9
Fixes b/269515918, where the prefix
)]}'\n
for Cross-site script inclusion (XSSI) didn't work for GsonFactory.Users will call
GsonFactory.builder().setReadLeniency(true).build()
when they want this library to process JSON input that may have the prefix.withReadLeniency()
gives flexibility for us to choose writeLeniency in future if necessary. (It's possible that read leniency is true and write leniency is false.)BEGIN_COMMIT_OVERRIDE
feat: GsonFactory to have read leniency option via
GsonFactory.builder().setReadLeniency(true).build()
END_COMMIT_OVERRIDE