|
16 | 16 |
|
17 | 17 | package com.google.gson; |
18 | 18 |
|
19 | | -import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS; |
20 | | -import static com.google.gson.Gson.DEFAULT_DATE_PATTERN; |
21 | | -import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML; |
22 | | -import static com.google.gson.Gson.DEFAULT_FORMATTING_STYLE; |
23 | | -import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE; |
24 | | -import static com.google.gson.Gson.DEFAULT_NUMBER_TO_NUMBER_STRATEGY; |
25 | | -import static com.google.gson.Gson.DEFAULT_OBJECT_TO_NUMBER_STRATEGY; |
26 | | -import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS; |
27 | | -import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES; |
28 | | -import static com.google.gson.Gson.DEFAULT_STRICTNESS; |
29 | | -import static com.google.gson.Gson.DEFAULT_USE_JDK_UNSAFE; |
30 | | - |
31 | 19 | import com.google.errorprone.annotations.CanIgnoreReturnValue; |
32 | 20 | import com.google.errorprone.annotations.InlineMe; |
33 | 21 | import com.google.gson.annotations.Since; |
34 | 22 | import com.google.gson.annotations.Until; |
| 23 | +import com.google.gson.internal.ConstructorConstructor; |
35 | 24 | import com.google.gson.internal.Excluder; |
| 25 | +import com.google.gson.internal.bind.ArrayTypeAdapter; |
| 26 | +import com.google.gson.internal.bind.CollectionTypeAdapterFactory; |
36 | 27 | import com.google.gson.internal.bind.DefaultDateTypeAdapter; |
| 28 | +import com.google.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory; |
| 29 | +import com.google.gson.internal.bind.MapTypeAdapterFactory; |
| 30 | +import com.google.gson.internal.bind.NumberTypeAdapter; |
| 31 | +import com.google.gson.internal.bind.ObjectTypeAdapter; |
| 32 | +import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; |
37 | 33 | import com.google.gson.internal.bind.TreeTypeAdapter; |
38 | 34 | import com.google.gson.internal.bind.TypeAdapters; |
39 | 35 | import com.google.gson.internal.sql.SqlTypesSupport; |
|
45 | 41 | import java.text.SimpleDateFormat; |
46 | 42 | import java.util.ArrayDeque; |
47 | 43 | import java.util.ArrayList; |
| 44 | +import java.util.Arrays; |
| 45 | +import java.util.Collection; |
48 | 46 | import java.util.Collections; |
49 | 47 | import java.util.Date; |
50 | 48 | import java.util.HashMap; |
51 | 49 | import java.util.List; |
52 | 50 | import java.util.Map; |
53 | 51 | import java.util.Objects; |
| 52 | +import java.util.concurrent.atomic.AtomicLong; |
| 53 | +import java.util.concurrent.atomic.AtomicLongArray; |
54 | 54 |
|
55 | 55 | /** |
56 | 56 | * Use this builder to construct a {@link Gson} instance when you need to set configuration options |
|
90 | 90 | * @author Jesse Wilson |
91 | 91 | */ |
92 | 92 | public final class GsonBuilder { |
93 | | - private Excluder excluder = Excluder.DEFAULT; |
94 | | - private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT; |
95 | | - private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY; |
96 | | - private final Map<Type, InstanceCreator<?>> instanceCreators = new HashMap<>(); |
97 | | - private final List<TypeAdapterFactory> factories = new ArrayList<>(); |
| 93 | + private static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; |
| 94 | + // Strictness of `null` is the legacy mode where some Gson APIs are always lenient |
| 95 | + private static final Strictness DEFAULT_STRICTNESS = null; |
| 96 | + private static final FormattingStyle DEFAULT_FORMATTING_STYLE = FormattingStyle.COMPACT; |
| 97 | + private static final boolean DEFAULT_ESCAPE_HTML = true; |
| 98 | + private static final boolean DEFAULT_SERIALIZE_NULLS = false; |
| 99 | + private static final boolean DEFAULT_COMPLEX_MAP_KEYS = false; |
| 100 | + private static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false; |
| 101 | + private static final boolean DEFAULT_USE_JDK_UNSAFE = true; |
| 102 | + private static final String DEFAULT_DATE_PATTERN = null; |
| 103 | + private static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY = |
| 104 | + FieldNamingPolicy.IDENTITY; |
| 105 | + private static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE; |
| 106 | + private static final ToNumberStrategy DEFAULT_NUMBER_TO_NUMBER_STRATEGY = |
| 107 | + ToNumberPolicy.LAZILY_PARSED_NUMBER; |
| 108 | + |
| 109 | + static final ConstructorConstructor DEFAULT_CONSTRUCTOR_CONSTRUCTOR = |
| 110 | + new ConstructorConstructor( |
| 111 | + Collections.emptyMap(), DEFAULT_USE_JDK_UNSAFE, Collections.emptyList()); |
| 112 | + |
| 113 | + static final JsonAdapterAnnotationTypeAdapterFactory |
| 114 | + DEFAULT_JSON_ADAPTER_ANNOTATION_TYPE_ADAPTER_FACTORY = |
| 115 | + new JsonAdapterAnnotationTypeAdapterFactory(DEFAULT_CONSTRUCTOR_CONSTRUCTOR); |
| 116 | + |
| 117 | + /** |
| 118 | + * Default instance of the builder, to be used only by the default {@link Gson#Gson()} |
| 119 | + * constructor. Must not be used for anything else and must not be leaked to user code, since that |
| 120 | + * could lead to accidental modification of this default builder. |
| 121 | + */ |
| 122 | + static final GsonBuilder DEFAULT = new GsonBuilder(); |
| 123 | + |
| 124 | + static final List<TypeAdapterFactory> DEFAULT_TYPE_ADAPTER_FACTORIES = |
| 125 | + GsonBuilder.DEFAULT.createFactories( |
| 126 | + DEFAULT_CONSTRUCTOR_CONSTRUCTOR, DEFAULT_JSON_ADAPTER_ANNOTATION_TYPE_ADAPTER_FACTORY); |
| 127 | + |
| 128 | + Excluder excluder = Excluder.DEFAULT; |
| 129 | + LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT; |
| 130 | + FieldNamingStrategy fieldNamingPolicy = DEFAULT_FIELD_NAMING_STRATEGY; |
| 131 | + final Map<Type, InstanceCreator<?>> instanceCreators = new HashMap<>(); |
| 132 | + final List<TypeAdapterFactory> factories = new ArrayList<>(); |
98 | 133 |
|
99 | 134 | /** tree-style hierarchy factories. These come after factories for backwards compatibility. */ |
100 | | - private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<>(); |
101 | | - |
102 | | - private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; |
103 | | - private String datePattern = DEFAULT_DATE_PATTERN; |
104 | | - private int dateStyle = DateFormat.DEFAULT; |
105 | | - private int timeStyle = DateFormat.DEFAULT; |
106 | | - private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; |
107 | | - private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES; |
108 | | - private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML; |
109 | | - private FormattingStyle formattingStyle = DEFAULT_FORMATTING_STYLE; |
110 | | - private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE; |
111 | | - private Strictness strictness = DEFAULT_STRICTNESS; |
112 | | - private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE; |
113 | | - private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY; |
114 | | - private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY; |
115 | | - private final ArrayDeque<ReflectionAccessFilter> reflectionFilters = new ArrayDeque<>(); |
| 135 | + final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<>(); |
| 136 | + |
| 137 | + boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; |
| 138 | + String datePattern = DEFAULT_DATE_PATTERN; |
| 139 | + int dateStyle = DateFormat.DEFAULT; |
| 140 | + int timeStyle = DateFormat.DEFAULT; |
| 141 | + boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; |
| 142 | + boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES; |
| 143 | + boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML; |
| 144 | + FormattingStyle formattingStyle = DEFAULT_FORMATTING_STYLE; |
| 145 | + boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE; |
| 146 | + Strictness strictness = DEFAULT_STRICTNESS; |
| 147 | + boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE; |
| 148 | + ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY; |
| 149 | + ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY; |
| 150 | + final ArrayDeque<ReflectionAccessFilter> reflectionFilters = new ArrayDeque<>(); |
116 | 151 |
|
117 | 152 | /** |
118 | 153 | * Creates a GsonBuilder instance that can be used to build Gson with various configuration |
@@ -884,43 +919,123 @@ public GsonBuilder addReflectionAccessFilter(ReflectionAccessFilter filter) { |
884 | 919 | * @return an instance of Gson configured with the options currently set in this builder |
885 | 920 | */ |
886 | 921 | public Gson create() { |
887 | | - List<TypeAdapterFactory> factories = |
888 | | - new ArrayList<>(this.factories.size() + this.hierarchyFactories.size() + 3); |
889 | | - factories.addAll(this.factories); |
890 | | - Collections.reverse(factories); |
891 | | - |
892 | | - List<TypeAdapterFactory> hierarchyFactories = new ArrayList<>(this.hierarchyFactories); |
893 | | - Collections.reverse(hierarchyFactories); |
894 | | - factories.addAll(hierarchyFactories); |
895 | | - |
896 | | - addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories); |
897 | | - |
898 | | - return new Gson( |
899 | | - excluder, |
900 | | - fieldNamingPolicy, |
901 | | - new HashMap<>(instanceCreators), |
902 | | - serializeNulls, |
903 | | - complexMapKeySerialization, |
904 | | - generateNonExecutableJson, |
905 | | - escapeHtmlChars, |
906 | | - formattingStyle, |
907 | | - strictness, |
908 | | - serializeSpecialFloatingPointValues, |
909 | | - useJdkUnsafe, |
910 | | - longSerializationPolicy, |
911 | | - datePattern, |
912 | | - dateStyle, |
913 | | - timeStyle, |
914 | | - new ArrayList<>(this.factories), |
915 | | - new ArrayList<>(this.hierarchyFactories), |
916 | | - factories, |
917 | | - objectToNumberStrategy, |
918 | | - numberToNumberStrategy, |
919 | | - new ArrayList<>(reflectionFilters)); |
920 | | - } |
921 | | - |
922 | | - private static void addTypeAdaptersForDate( |
923 | | - String datePattern, int dateStyle, int timeStyle, List<TypeAdapterFactory> factories) { |
| 922 | + return new Gson(this); |
| 923 | + } |
| 924 | + |
| 925 | + List<TypeAdapterFactory> createFactories( |
| 926 | + ConstructorConstructor constructorConstructor, |
| 927 | + JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory) { |
| 928 | + ArrayList<TypeAdapterFactory> factories = new ArrayList<>(); |
| 929 | + |
| 930 | + // built-in type adapters that cannot be overridden |
| 931 | + factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); |
| 932 | + factories.add(ObjectTypeAdapter.getFactory(objectToNumberStrategy)); |
| 933 | + |
| 934 | + // the excluder must precede all adapters that handle user-defined types |
| 935 | + factories.add(excluder); |
| 936 | + |
| 937 | + // users' type adapters |
| 938 | + addUserDefinedAdapters(factories); |
| 939 | + |
| 940 | + // custom Date adapters |
| 941 | + addDateTypeAdapters(factories); |
| 942 | + |
| 943 | + // type adapters for basic platform types |
| 944 | + factories.add(TypeAdapters.STRING_FACTORY); |
| 945 | + factories.add(TypeAdapters.INTEGER_FACTORY); |
| 946 | + factories.add(TypeAdapters.BOOLEAN_FACTORY); |
| 947 | + factories.add(TypeAdapters.BYTE_FACTORY); |
| 948 | + factories.add(TypeAdapters.SHORT_FACTORY); |
| 949 | + TypeAdapter<Number> longAdapter = longSerializationPolicy.typeAdapter(); |
| 950 | + factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); |
| 951 | + factories.add(TypeAdapters.newFactory(double.class, Double.class, doubleAdapter())); |
| 952 | + factories.add(TypeAdapters.newFactory(float.class, Float.class, floatAdapter())); |
| 953 | + factories.add(NumberTypeAdapter.getFactory(numberToNumberStrategy)); |
| 954 | + factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY); |
| 955 | + factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY); |
| 956 | + factories.add( |
| 957 | + TypeAdapters.newFactory(AtomicLong.class, TypeAdapters.atomicLongAdapter(longAdapter))); |
| 958 | + factories.add( |
| 959 | + TypeAdapters.newFactory( |
| 960 | + AtomicLongArray.class, TypeAdapters.atomicLongArrayAdapter(longAdapter))); |
| 961 | + factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY); |
| 962 | + factories.add(TypeAdapters.CHARACTER_FACTORY); |
| 963 | + factories.add(TypeAdapters.STRING_BUILDER_FACTORY); |
| 964 | + factories.add(TypeAdapters.STRING_BUFFER_FACTORY); |
| 965 | + factories.add(TypeAdapters.BIG_DECIMAL_FACTORY); |
| 966 | + factories.add(TypeAdapters.BIG_INTEGER_FACTORY); |
| 967 | + // Add adapter for LazilyParsedNumber because user can obtain it from Gson and then try to |
| 968 | + // serialize it again |
| 969 | + factories.add(TypeAdapters.LAZILY_PARSED_NUMBER_FACTORY); |
| 970 | + factories.add(TypeAdapters.URL_FACTORY); |
| 971 | + factories.add(TypeAdapters.URI_FACTORY); |
| 972 | + factories.add(TypeAdapters.UUID_FACTORY); |
| 973 | + factories.add(TypeAdapters.CURRENCY_FACTORY); |
| 974 | + factories.add(TypeAdapters.LOCALE_FACTORY); |
| 975 | + factories.add(TypeAdapters.INET_ADDRESS_FACTORY); |
| 976 | + factories.add(TypeAdapters.BIT_SET_FACTORY); |
| 977 | + factories.add(DefaultDateTypeAdapter.DEFAULT_STYLE_FACTORY); |
| 978 | + factories.add(TypeAdapters.CALENDAR_FACTORY); |
| 979 | + factories.addAll(SqlTypesSupport.SQL_TYPE_FACTORIES); |
| 980 | + factories.add(ArrayTypeAdapter.FACTORY); |
| 981 | + factories.add(TypeAdapters.CLASS_FACTORY); |
| 982 | + |
| 983 | + // type adapters for composite and user-defined types |
| 984 | + factories.add(new CollectionTypeAdapterFactory(constructorConstructor)); |
| 985 | + factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)); |
| 986 | + factories.add(jsonAdapterFactory); |
| 987 | + factories.add(TypeAdapters.ENUM_FACTORY); |
| 988 | + factories.add( |
| 989 | + new ReflectiveTypeAdapterFactory( |
| 990 | + constructorConstructor, |
| 991 | + fieldNamingPolicy, |
| 992 | + excluder, |
| 993 | + jsonAdapterFactory, |
| 994 | + newImmutableList(reflectionFilters))); |
| 995 | + |
| 996 | + factories.trimToSize(); |
| 997 | + return Collections.unmodifiableList(factories); |
| 998 | + } |
| 999 | + |
| 1000 | + static <E> List<E> newImmutableList(Collection<E> collection) { |
| 1001 | + if (collection.isEmpty()) { |
| 1002 | + return Collections.emptyList(); |
| 1003 | + } |
| 1004 | + if (collection.size() == 1) { |
| 1005 | + return Collections.singletonList( |
| 1006 | + collection instanceof List |
| 1007 | + ? ((List<E>) collection).get(0) |
| 1008 | + : collection.iterator().next()); |
| 1009 | + } |
| 1010 | + @SuppressWarnings("unchecked") |
| 1011 | + List<E> list = (List<E>) Collections.unmodifiableList(Arrays.asList(collection.toArray())); |
| 1012 | + return list; |
| 1013 | + } |
| 1014 | + |
| 1015 | + private TypeAdapter<Number> doubleAdapter() { |
| 1016 | + return serializeSpecialFloatingPointValues ? TypeAdapters.DOUBLE : TypeAdapters.DOUBLE_STRICT; |
| 1017 | + } |
| 1018 | + |
| 1019 | + private TypeAdapter<Number> floatAdapter() { |
| 1020 | + return serializeSpecialFloatingPointValues ? TypeAdapters.FLOAT : TypeAdapters.FLOAT_STRICT; |
| 1021 | + } |
| 1022 | + |
| 1023 | + private void addUserDefinedAdapters(List<TypeAdapterFactory> all) { |
| 1024 | + if (!this.factories.isEmpty()) { |
| 1025 | + List<TypeAdapterFactory> reversedFactories = new ArrayList<>(this.factories); |
| 1026 | + Collections.reverse(reversedFactories); |
| 1027 | + all.addAll(reversedFactories); |
| 1028 | + } |
| 1029 | + |
| 1030 | + if (!this.hierarchyFactories.isEmpty()) { |
| 1031 | + List<TypeAdapterFactory> reversedHierarchyFactories = |
| 1032 | + new ArrayList<>(this.hierarchyFactories); |
| 1033 | + Collections.reverse(reversedHierarchyFactories); |
| 1034 | + all.addAll(reversedHierarchyFactories); |
| 1035 | + } |
| 1036 | + } |
| 1037 | + |
| 1038 | + private void addDateTypeAdapters(List<TypeAdapterFactory> factories) { |
924 | 1039 | TypeAdapterFactory dateAdapterFactory; |
925 | 1040 | boolean sqlTypesSupported = SqlTypesSupport.SUPPORTS_SQL_TYPES; |
926 | 1041 | TypeAdapterFactory sqlTimestampAdapterFactory = null; |
|
0 commit comments