Skip to content

Commit

Permalink
Add newBuilder() API (google#1142)
Browse files Browse the repository at this point in the history
* Add Gson.newBuilder API.

* Remove redundant test.

* Address Codacy comments.

* Reduce visibility of GsonBuilder constructor.
  • Loading branch information
naturalwarren authored and inder123 committed Sep 21, 2017
1 parent a8f7acd commit 08bbb22
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 18 deletions.
64 changes: 49 additions & 15 deletions gson/src/main/java/com/google/gson/Gson.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -124,18 +125,28 @@ public final class Gson {

private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>>();

private final List<TypeAdapterFactory> factories;
private final ConstructorConstructor constructorConstructor;

private final Excluder excluder;
private final FieldNamingStrategy fieldNamingStrategy;
private final boolean serializeNulls;
private final boolean htmlSafe;
private final boolean generateNonExecutableJson;
private final boolean prettyPrinting;
private final boolean lenient;
private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;

final List<TypeAdapterFactory> factories;

final Excluder excluder;
final FieldNamingStrategy fieldNamingStrategy;
final Map<Type, InstanceCreator<?>> instanceCreators;
final boolean serializeNulls;
final boolean complexMapKeySerialization;
final boolean generateNonExecutableJson;
final boolean htmlSafe;
final boolean prettyPrinting;
final boolean lenient;
final boolean serializeSpecialFloatingPointValues;
final String datePattern;
final int dateStyle;
final int timeStyle;
final LongSerializationPolicy longSerializationPolicy;
final List<TypeAdapterFactory> builderFactories;
final List<TypeAdapterFactory> builderHierarchyFactories;

/**
* Constructs a Gson object with default configuration. The default configuration has the
* following settings:
Expand Down Expand Up @@ -175,23 +186,36 @@ public Gson() {
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
LongSerializationPolicy.DEFAULT, Collections.<TypeAdapterFactory>emptyList());
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT, DateFormat.DEFAULT,
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
Collections.<TypeAdapterFactory>emptyList());
}

Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
List<TypeAdapterFactory> typeAdapterFactories) {
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
int timeStyle, List<TypeAdapterFactory> builderFactories,
List<TypeAdapterFactory> builderHierarchyFactories,
List<TypeAdapterFactory> factoriesToBeAdded) {
this.excluder = excluder;
this.fieldNamingStrategy = fieldNamingStrategy;
this.instanceCreators = instanceCreators;
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.complexMapKeySerialization = complexMapKeySerialization;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
this.lenient = lenient;
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
this.longSerializationPolicy = longSerializationPolicy;
this.datePattern = datePattern;
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.builderFactories = builderFactories;
this.builderHierarchyFactories = builderHierarchyFactories;

List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

Expand All @@ -202,8 +226,8 @@ public Gson() {
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);

// user's type adapters
factories.addAll(typeAdapterFactories);
// users' type adapters
factories.addAll(factoriesToBeAdded);

// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
Expand Down Expand Up @@ -255,6 +279,16 @@ public Gson() {
this.factories = Collections.unmodifiableList(factories);
}

/**
* Returns a new GsonBuilder containing all custom factories and configuration used by the current
* instance.
*
* @return a GsonBuilder instance.
*/
public GsonBuilder newBuilder() {
return new GsonBuilder(this);
}

public Excluder excluder() {
return excluder;
}
Expand Down
29 changes: 28 additions & 1 deletion gson/src/main/java/com/google/gson/GsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,31 @@ public final class GsonBuilder {
public GsonBuilder() {
}

/**
* Constructs a GsonBuilder instance from a Gson instance. The newly constructed GsonBuilder
* has the same configuration as the previously built Gson instance.
*
* @param gson the gson instance whose configuration should by applied to a new GsonBuilder.
*/
GsonBuilder(Gson gson) {
this.excluder = gson.excluder;
this.fieldNamingPolicy = gson.fieldNamingStrategy;
this.instanceCreators.putAll(gson.instanceCreators);
this.serializeNulls = gson.serializeNulls;
this.complexMapKeySerialization = gson.complexMapKeySerialization;
this.generateNonExecutableJson = gson.generateNonExecutableJson;
this.escapeHtmlChars = gson.htmlSafe;
this.prettyPrinting = gson.prettyPrinting;
this.lenient = gson.lenient;
this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues;
this.longSerializationPolicy = gson.longSerializationPolicy;
this.datePattern = gson.datePattern;
this.dateStyle = gson.dateStyle;
this.timeStyle = gson.timeStyle;
this.factories.addAll(gson.builderFactories);
this.hierarchyFactories.addAll(gson.builderHierarchyFactories);
}

/**
* Configures Gson to enable versioning support.
*
Expand Down Expand Up @@ -572,7 +597,9 @@ public Gson create() {
return new Gson(excluder, fieldNamingPolicy, instanceCreators,
serializeNulls, complexMapKeySerialization,
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
serializeSpecialFloatingPointValues, longSerializationPolicy, factories);
serializeSpecialFloatingPointValues, longSerializationPolicy,
datePattern, dateStyle, timeStyle,
this.factories, this.hierarchyFactories, factories);
}

@SuppressWarnings("unchecked")
Expand Down
30 changes: 28 additions & 2 deletions gson/src/test/java/com/google/gson/GsonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
package com.google.gson;

import com.google.gson.internal.Excluder;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import junit.framework.TestCase;
Expand All @@ -43,12 +47,34 @@ public final class GsonTest extends TestCase {
public void testOverridesDefaultExcluder() {
Gson gson = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
new HashMap<Type, InstanceCreator<?>>(), true, false, true, false,
true, true, false, LongSerializationPolicy.DEFAULT,
new ArrayList<TypeAdapterFactory>());
true, true, false, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>());

assertEquals(CUSTOM_EXCLUDER, gson.excluder());
assertEquals(CUSTOM_FIELD_NAMING_STRATEGY, gson.fieldNamingStrategy());
assertEquals(true, gson.serializeNulls());
assertEquals(false, gson.htmlSafe());
}

public void testClonedTypeAdapterFactoryListsAreIndependent() {
Gson original = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
new HashMap<Type, InstanceCreator<?>>(), true, false, true, false,
true, true, false, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>());

Gson clone = original.newBuilder()
.registerTypeAdapter(Object.class, new TestTypeAdapter())
.create();

assertEquals(original.factories.size() + 1, clone.factories.size());
}

private static final class TestTypeAdapter extends TypeAdapter<Object> {
@Override public void write(JsonWriter out, Object value) throws IOException {
// Test stub.
}
@Override public Object read(JsonReader in) throws IOException { return null; }
}
}

0 comments on commit 08bbb22

Please sign in to comment.