builderFactories,
@@ -266,7 +277,7 @@ public Gson() {
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.formattingStyle = formattingStyle;
- this.lenient = lenient;
+ this.strictness = strictness;
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
this.useJdkUnsafe = useJdkUnsafe;
this.longSerializationPolicy = longSerializationPolicy;
@@ -820,7 +831,7 @@ public void toJson(Object src, Appendable writer) throws JsonIOException {
*
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
*
- * @param writer Writer to which the JSON representation of src needs to be written.
+ * @param writer Writer to which the JSON representation of src needs to be written
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.2
*
@@ -840,24 +851,38 @@ public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOE
* Writes the JSON representation of {@code src} of type {@code typeOfSrc} to
* {@code writer}.
*
- * The JSON data is written in {@linkplain JsonWriter#setLenient(boolean) lenient mode},
- * regardless of the lenient mode setting of the provided writer. The lenient mode setting
- * of the writer is restored once this method returns.
+ *
If the {@code Gson} instance has an {@linkplain GsonBuilder#setStrictness(Strictness) explicit strictness setting},
+ * this setting will be used for writing the JSON regardless of the {@linkplain JsonWriter#getStrictness() strictness}
+ * of the provided {@link JsonWriter}. For legacy reasons, if the {@code Gson} instance has no explicit strictness setting
+ * and the writer does not have the strictness {@link Strictness#STRICT}, the JSON will be written in {@link Strictness#LENIENT}
+ * mode.
+ * Note that in all cases the old strictness setting of the writer will be restored when this method returns.
*
*
The 'HTML-safe' and 'serialize {@code null}' settings of this {@code Gson} instance
* (configured by the {@link GsonBuilder}) are applied, and the original settings of the
* writer are restored once this method returns.
*
+ * @param src the object for which JSON representation is to be created
+ * @param typeOfSrc the type of the object to be written
+ * @param writer Writer to which the JSON representation of src needs to be written
+ *
* @throws JsonIOException if there was a problem writing to the writer
*/
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
@SuppressWarnings("unchecked")
TypeAdapter adapter = (TypeAdapter) getAdapter(TypeToken.get(typeOfSrc));
- boolean oldLenient = writer.isLenient();
- writer.setLenient(true);
+
+ Strictness oldStrictness = writer.getStrictness();
+ if (this.strictness != null) {
+ writer.setStrictness(this.strictness);
+ } else if (writer.getStrictness() != Strictness.STRICT) {
+ writer.setStrictness(Strictness.LENIENT);
+ }
+
boolean oldHtmlSafe = writer.isHtmlSafe();
- writer.setHtmlSafe(htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
+
+ writer.setHtmlSafe(htmlSafe);
writer.setSerializeNulls(serializeNulls);
try {
adapter.write(writer, src);
@@ -866,7 +891,7 @@ public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOE
} catch (AssertionError e) {
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
} finally {
- writer.setLenient(oldLenient);
+ writer.setStrictness(oldStrictness);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
@@ -910,7 +935,10 @@ public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOExce
* {@link GsonBuilder#disableHtmlEscaping()}
* {@link GsonBuilder#generateNonExecutableJson()}
* {@link GsonBuilder#serializeNulls()}
- * {@link GsonBuilder#setLenient()}
+ * {@link GsonBuilder#setStrictness(Strictness)}. If no
+ * {@linkplain GsonBuilder#setStrictness(Strictness) explicit strictness has been set} the created
+ * writer will have a strictness of {@link Strictness#LEGACY_STRICT}. Otherwise, the strictness of
+ * the {@code Gson} instance will be used for the created writer.
* {@link GsonBuilder#setPrettyPrinting()}
* {@link GsonBuilder#setFormattingStyle(FormattingStyle)}
*
@@ -922,7 +950,7 @@ public JsonWriter newJsonWriter(Writer writer) throws IOException {
JsonWriter jsonWriter = new JsonWriter(writer);
jsonWriter.setFormattingStyle(formattingStyle);
jsonWriter.setHtmlSafe(htmlSafe);
- jsonWriter.setLenient(lenient);
+ jsonWriter.setStrictness(strictness == null ? Strictness.LEGACY_STRICT : strictness);
jsonWriter.setSerializeNulls(serializeNulls);
return jsonWriter;
}
@@ -932,35 +960,50 @@ public JsonWriter newJsonWriter(Writer writer) throws IOException {
*
* The following settings are considered:
*
- * {@link GsonBuilder#setLenient()}
+ * {@link GsonBuilder#setStrictness(Strictness)}. If no
+ * {@linkplain GsonBuilder#setStrictness(Strictness) explicit strictness has been set} the created
+ * reader will have a strictness of {@link Strictness#LEGACY_STRICT}. Otherwise, the strictness of
+ * the {@code Gson} instance will be used for the created reader.
*
*/
public JsonReader newJsonReader(Reader reader) {
JsonReader jsonReader = new JsonReader(reader);
- jsonReader.setLenient(lenient);
+ jsonReader.setStrictness(strictness == null ? Strictness.LEGACY_STRICT : strictness);
return jsonReader;
}
/**
* Writes the JSON for {@code jsonElement} to {@code writer}.
*
- * The JSON data is written in {@linkplain JsonWriter#setLenient(boolean) lenient mode},
- * regardless of the lenient mode setting of the provided writer. The lenient mode setting
- * of the writer is restored once this method returns.
+ *
If the {@code Gson} instance has an {@linkplain GsonBuilder#setStrictness(Strictness) explicit strictness setting},
+ * this setting will be used for writing the JSON regardless of the {@linkplain JsonWriter#getStrictness() strictness}
+ * of the provided {@link JsonWriter}. For legacy reasons, if the {@code Gson} instance has no explicit strictness setting
+ * and the writer does not have the strictness {@link Strictness#STRICT}, the JSON will be written in {@link Strictness#LENIENT}
+ * mode.
+ * Note that in all cases the old strictness setting of the writer will be restored when this method returns.
*
*
The 'HTML-safe' and 'serialize {@code null}' settings of this {@code Gson} instance
* (configured by the {@link GsonBuilder}) are applied, and the original settings of the
* writer are restored once this method returns.
*
+ * @param jsonElement the JSON element to be written
+ * @param writer the JSON writer to which the provided element will be written
* @throws JsonIOException if there was a problem writing to the writer
*/
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
- boolean oldLenient = writer.isLenient();
- writer.setLenient(true);
+ Strictness oldStrictness = writer.getStrictness();
boolean oldHtmlSafe = writer.isHtmlSafe();
- writer.setHtmlSafe(htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
+
+ writer.setHtmlSafe(htmlSafe);
writer.setSerializeNulls(serializeNulls);
+
+ if (this.strictness != null) {
+ writer.setStrictness(this.strictness);
+ } else if (writer.getStrictness() != Strictness.STRICT) {
+ writer.setStrictness(Strictness.LENIENT);
+ }
+
try {
Streams.write(jsonElement, writer);
} catch (IOException e) {
@@ -968,7 +1011,7 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce
} catch (AssertionError e) {
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
} finally {
- writer.setLenient(oldLenient);
+ writer.setStrictness(oldStrictness);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
@@ -1187,9 +1230,12 @@ private static void assertFullConsumption(Object obj, JsonReader reader) {
*
Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
* multiple top-level JSON elements, or if there is trailing data.
*
- *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
- * regardless of the lenient mode setting of the provided reader. The lenient mode setting
- * of the reader is restored once this method returns.
+ *
If the {@code Gson} instance has an {@linkplain GsonBuilder#setStrictness(Strictness) explicit strictness setting},
+ * this setting will be used for reading the JSON regardless of the {@linkplain JsonReader#getStrictness() strictness}
+ * of the provided {@link JsonReader}. For legacy reasons, if the {@code Gson} instance has no explicit strictness setting
+ * and the reader does not have the strictness {@link Strictness#STRICT}, the JSON will be written in {@link Strictness#LENIENT}
+ * mode.
+ * Note that in all cases the old strictness setting of the reader will be restored when this method returns.
*
* @param the type of the desired object
* @param reader the reader whose next JSON value should be deserialized
@@ -1216,9 +1262,12 @@ public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J
* Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
* multiple top-level JSON elements, or if there is trailing data.
*
- *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
- * regardless of the lenient mode setting of the provided reader. The lenient mode setting
- * of the reader is restored once this method returns.
+ *
If the {@code Gson} instance has an {@linkplain GsonBuilder#setStrictness(Strictness) explicit strictness setting},
+ * this setting will be used for reading the JSON regardless of the {@linkplain JsonReader#getStrictness() strictness}
+ * of the provided {@link JsonReader}. For legacy reasons, if the {@code Gson} instance has no explicit strictness setting
+ * and the reader does not have the strictness {@link Strictness#STRICT}, the JSON will be written in {@link Strictness#LENIENT}
+ * mode.
+ * Note that in all cases the old strictness setting of the reader will be restored when this method returns.
*
* @param the type of the desired object
* @param reader the reader whose next JSON value should be deserialized
@@ -1238,8 +1287,14 @@ public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J
*/
public T fromJson(JsonReader reader, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
- boolean oldLenient = reader.isLenient();
- reader.setLenient(true);
+ Strictness oldStrictness = reader.getStrictness();
+
+ if (this.strictness != null) {
+ reader.setStrictness(this.strictness);
+ } else if (reader.getStrictness() != Strictness.STRICT) {
+ reader.setStrictness(Strictness.LENIENT);
+ }
+
try {
JsonToken unused = reader.peek();
isEmpty = false;
@@ -1262,7 +1317,7 @@ public T fromJson(JsonReader reader, TypeToken typeOfT) throws JsonIOExce
} catch (AssertionError e) {
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
} finally {
- reader.setLenient(oldLenient);
+ reader.setStrictness(oldStrictness);
}
}
diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java
index e3d4818233..68eb7d718b 100644
--- a/gson/src/main/java/com/google/gson/GsonBuilder.java
+++ b/gson/src/main/java/com/google/gson/GsonBuilder.java
@@ -21,14 +21,15 @@
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
import static com.google.gson.Gson.DEFAULT_FORMATTING_STYLE;
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
-import static com.google.gson.Gson.DEFAULT_LENIENT;
import static com.google.gson.Gson.DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
import static com.google.gson.Gson.DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
+import static com.google.gson.Gson.DEFAULT_STRICTNESS;
import static com.google.gson.Gson.DEFAULT_USE_JDK_UNSAFE;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.errorprone.annotations.InlineMe;
import com.google.gson.annotations.Since;
import com.google.gson.annotations.Until;
import com.google.gson.internal.$Gson$Preconditions;
@@ -57,8 +58,7 @@
* use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
* various configuration methods, and finally calling create.
*
- * The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
- * instance:
+ *
The following example shows how to use the {@code GsonBuilder} to construct a Gson instance:
*
*
* Gson gson = new GsonBuilder()
@@ -72,12 +72,16 @@
* .create();
*
*
- * NOTES:
+ *
Notes:
*
- * the order of invocation of configuration methods does not matter.
- * The default serialization of {@link Date} and its subclasses in Gson does
+ * The order of invocation of configuration methods does not matter.
+ * The default serialization of {@link Date} and its subclasses in Gson does
* not contain time-zone information. So, if you are using date/time instances,
* use {@code GsonBuilder} and its {@code setDateFormat} methods.
+ * By default no explicit {@link Strictness} is set; some of the {@link Gson} methods
+ * behave as if {@link Strictness#LEGACY_STRICT} was used whereas others behave as
+ * if {@link Strictness#LENIENT} was used. Prefer explicitly setting a strictness
+ * with {@link #setStrictness(Strictness)} to avoid this legacy behavior.
*
*
* @author Inderjeet Singh
@@ -101,7 +105,7 @@ public final class GsonBuilder {
private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML;
private FormattingStyle formattingStyle = DEFAULT_FORMATTING_STYLE;
private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
- private boolean lenient = DEFAULT_LENIENT;
+ private Strictness strictness = DEFAULT_STRICTNESS;
private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
@@ -120,7 +124,7 @@ 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.
+ * @param gson the gson instance whose configuration should be applied to a new GsonBuilder.
*/
GsonBuilder(Gson gson) {
this.excluder = gson.excluder;
@@ -131,7 +135,7 @@ public GsonBuilder() {
this.generateNonExecutableJson = gson.generateNonExecutableJson;
this.escapeHtmlChars = gson.htmlSafe;
this.formattingStyle = gson.formattingStyle;
- this.lenient = gson.lenient;
+ this.strictness = gson.strictness;
this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues;
this.longSerializationPolicy = gson.longSerializationPolicy;
this.datePattern = gson.datePattern;
@@ -274,7 +278,7 @@ public GsonBuilder serializeNulls() {
* {"x":2,"y":3}}.
*
* Given the assumption above, a {@code Map} will be
- * serialize as an array of arrays (can be viewed as an entry set of pairs).
+ * serialized as an array of arrays (can be viewed as an entry set of pairs).
*
* Below is an example of serializing complex types as JSON arrays:
*
{@code
@@ -522,18 +526,40 @@ public GsonBuilder setFormattingStyle(FormattingStyle formattingStyle) {
}
/**
- * Configures Gson to allow JSON data which does not strictly comply with the JSON specification.
+ * Sets the strictness of this builder to {@link Strictness#LENIENT}.
*
- * Note: Due to legacy reasons most methods of Gson are always lenient, regardless of
- * whether this builder method is used.
+ * @deprecated This method is equivalent to calling {@link #setStrictness(Strictness)} with
+ * {@link Strictness#LENIENT}: {@code setStrictness(Strictness.LENIENT)}
*
- * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
- * @see JsonReader#setLenient(boolean)
- * @see JsonWriter#setLenient(boolean)
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern.
+ * @see JsonReader#setStrictness(Strictness)
+ * @see JsonWriter#setStrictness(Strictness)
+ * @see #setStrictness(Strictness)
*/
+ @Deprecated
+ @InlineMe(replacement = "this.setStrictness(Strictness.LENIENT)", imports = "com.google.gson.Strictness")
@CanIgnoreReturnValue
public GsonBuilder setLenient() {
- lenient = true;
+ return setStrictness(Strictness.LENIENT);
+ }
+
+ /**
+ * Sets the strictness of this builder to the provided parameter.
+ *
+ *
This changes how strict the
+ * RFC 8259 JSON specification is enforced when parsing or
+ * writing JSON. For details on this, refer to {@link JsonReader#setStrictness(Strictness)} and
+ * {@link JsonWriter#setStrictness(Strictness)}.
+ *
+ * @param strictness the new strictness mode. May not be {@code null}.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern.
+ * @see JsonReader#setStrictness(Strictness)
+ * @see JsonWriter#setStrictness(Strictness)
+ * @since $next-version$
+ */
+ @CanIgnoreReturnValue
+ public GsonBuilder setStrictness(Strictness strictness) {
+ this.strictness = Objects.requireNonNull(strictness);
return this;
}
@@ -574,7 +600,7 @@ public GsonBuilder setDateFormat(String pattern) {
}
/**
- * Configures Gson to to serialize {@code Date} objects according to the style value provided.
+ * Configures Gson to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
@@ -595,7 +621,7 @@ public GsonBuilder setDateFormat(int style) {
}
/**
- * Configures Gson to to serialize {@code Date} objects according to the style value provided.
+ * Configures Gson to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
@@ -712,7 +738,7 @@ public GsonBuilder registerTypeHierarchyAdapter(Class> baseType, Object typeAd
}
/**
- * Section 2.4 of JSON specification disallows
+ * Section 6 of JSON specification disallows
* special double values (NaN, Infinity, -Infinity). However,
* Javascript
* specification (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
@@ -805,7 +831,7 @@ public Gson create() {
return new Gson(excluder, fieldNamingPolicy, new HashMap<>(instanceCreators),
serializeNulls, complexMapKeySerialization,
- generateNonExecutableJson, escapeHtmlChars, formattingStyle, lenient,
+ generateNonExecutableJson, escapeHtmlChars, formattingStyle, strictness,
serializeSpecialFloatingPointValues, useJdkUnsafe, longSerializationPolicy,
datePattern, dateStyle, timeStyle, new ArrayList<>(this.factories),
new ArrayList<>(this.hierarchyFactories), factories,
diff --git a/gson/src/main/java/com/google/gson/JsonElement.java b/gson/src/main/java/com/google/gson/JsonElement.java
index 23e5654aac..1b440d0532 100644
--- a/gson/src/main/java/com/google/gson/JsonElement.java
+++ b/gson/src/main/java/com/google/gson/JsonElement.java
@@ -321,7 +321,8 @@ public String toString() {
try {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
- jsonWriter.setLenient(true);
+ // Make writer lenient because toString() must not fail, even if for example JsonPrimitive contains NaN
+ jsonWriter.setStrictness(Strictness.LENIENT);
Streams.write(this, jsonWriter);
return stringWriter.toString();
} catch (IOException e) {
diff --git a/gson/src/main/java/com/google/gson/JsonParser.java b/gson/src/main/java/com/google/gson/JsonParser.java
index 20d3750cea..557d00c8e0 100644
--- a/gson/src/main/java/com/google/gson/JsonParser.java
+++ b/gson/src/main/java/com/google/gson/JsonParser.java
@@ -41,7 +41,7 @@ public JsonParser() {}
* An exception is thrown if the JSON string has multiple top-level JSON elements,
* or if there is trailing data.
*
- * The JSON string is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode}.
+ *
The JSON string is parsed in {@linkplain JsonReader#setStrictness(Strictness) lenient mode}.
*
* @param json JSON text
* @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
@@ -57,7 +57,7 @@ public static JsonElement parseString(String json) throws JsonSyntaxException {
* An exception is thrown if the JSON string has multiple top-level JSON elements,
* or if there is trailing data.
*
- *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode}.
+ *
The JSON data is parsed in {@linkplain JsonReader#setStrictness(Strictness) lenient mode}.
*
* @param reader JSON text
* @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
@@ -87,8 +87,8 @@ public static JsonElement parseReader(Reader reader) throws JsonIOException, Jso
* Unlike the other {@code parse} methods, no exception is thrown if the JSON data has
* multiple top-level JSON elements, or if there is trailing data.
*
- *
The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
- * regardless of the lenient mode setting of the provided reader. The lenient mode setting
+ *
The JSON data is parsed in {@linkplain JsonReader#setStrictness(Strictness) lenient mode},
+ * regardless of the strictness setting of the provided reader. The strictness setting
* of the reader is restored once this method returns.
*
* @throws JsonParseException if there is an IOException or if the specified
@@ -97,8 +97,8 @@ public static JsonElement parseReader(Reader reader) throws JsonIOException, Jso
*/
public static JsonElement parseReader(JsonReader reader)
throws JsonIOException, JsonSyntaxException {
- boolean lenient = reader.isLenient();
- reader.setLenient(true);
+ Strictness strictness = reader.getStrictness();
+ reader.setStrictness(Strictness.LENIENT);
try {
return Streams.parse(reader);
} catch (StackOverflowError e) {
@@ -106,7 +106,7 @@ public static JsonElement parseReader(JsonReader reader)
} catch (OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source: " + reader + " to Json", e);
} finally {
- reader.setLenient(lenient);
+ reader.setStrictness(strictness);
}
}
diff --git a/gson/src/main/java/com/google/gson/JsonStreamParser.java b/gson/src/main/java/com/google/gson/JsonStreamParser.java
index cbc2883ca8..7d2629368b 100644
--- a/gson/src/main/java/com/google/gson/JsonStreamParser.java
+++ b/gson/src/main/java/com/google/gson/JsonStreamParser.java
@@ -28,7 +28,7 @@
/**
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
* asynchronously. The JSON data is parsed in lenient mode, see also
- * {@link JsonReader#setLenient(boolean)}.
+ * {@link JsonReader#setStrictness(Strictness)}.
*
*
This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
* properly use this class across multiple threads, you will need to add some external
@@ -66,7 +66,7 @@ public JsonStreamParser(String json) {
*/
public JsonStreamParser(Reader reader) {
parser = new JsonReader(reader);
- parser.setLenient(true);
+ parser.setStrictness(Strictness.LENIENT);
lock = new Object();
}
diff --git a/gson/src/main/java/com/google/gson/Strictness.java b/gson/src/main/java/com/google/gson/Strictness.java
new file mode 100644
index 0000000000..f3bd3fe08f
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/Strictness.java
@@ -0,0 +1,29 @@
+package com.google.gson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * Modes that indicate how strictly a JSON {@linkplain JsonReader reader} or
+ * {@linkplain JsonWriter writer} follows the syntax laid out in the
+ * RFC 8259 JSON specification .
+ *
+ *
You can look at {@link JsonReader#setStrictness(Strictness)} to see how the strictness
+ * affects the {@link JsonReader} and you can look at
+ * {@link JsonWriter#setStrictness(Strictness)} to see how the strictness
+ * affects the {@link JsonWriter}.
+ *
+ * @see JsonReader#setStrictness(Strictness)
+ * @see JsonWriter#setStrictness(Strictness)
+ * @since $next-version$
+ */
+public enum Strictness {
+ /** Allow large deviations from the JSON specification. */
+ LENIENT,
+
+ /** Allow certain small deviations from the JSON specification for legacy reasons. */
+ LEGACY_STRICT,
+
+ /** Strict compliance with the JSON specification. */
+ STRICT
+}
diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java
index 5fdea225a5..d15b1e080c 100644
--- a/gson/src/main/java/com/google/gson/TypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/TypeAdapter.java
@@ -134,10 +134,10 @@ public TypeAdapter() {
/**
* Converts {@code value} to a JSON document and writes it to {@code out}.
- * Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson}
- * method, this write is strict. Create a {@link
- * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
- * {@link #write(JsonWriter, Object)} for lenient writing.
+ * The strictness {@link Strictness#LEGACY_STRICT} is used for writing the JSON data.
+ * To use a different strictness setting create a {@link JsonWriter}, call its
+ * {@link JsonWriter#setStrictness(Strictness)} method and then use
+ * {@link #write(JsonWriter, Object)} for writing.
*
* @param value the Java object to convert. May be null.
* @since 2.2
@@ -207,10 +207,11 @@ public final TypeAdapter nullSafe() {
}
/**
- * Converts {@code value} to a JSON document. Unlike Gson's similar {@link
- * Gson#toJson(Object) toJson} method, this write is strict. Create a {@link
- * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
- * {@link #write(JsonWriter, Object)} for lenient writing.
+ * Converts {@code value} to a JSON document.
+ * The strictness {@link Strictness#LEGACY_STRICT} is used for writing the JSON data.
+ * To use a different strictness setting create a {@link JsonWriter}, call its
+ * {@link JsonWriter#setStrictness(Strictness)} method and then use
+ * {@link #write(JsonWriter, Object)} for writing.
*
* @throws JsonIOException wrapping {@code IOException}s thrown by {@link #write(JsonWriter, Object)}
* @param value the Java object to convert. May be null.
@@ -253,10 +254,10 @@ public final JsonElement toJsonTree(T value) {
public abstract T read(JsonReader in) throws IOException;
/**
- * Converts the JSON document in {@code in} to a Java object. Unlike Gson's
- * similar {@link Gson#fromJson(Reader, Class) fromJson} method, this
- * read is strict. Create a {@link JsonReader#setLenient(boolean) lenient}
- * {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading.
+ * Converts the JSON document in {@code in} to a Java object. The strictness
+ * {@link Strictness#LEGACY_STRICT} is used for reading the JSON data. To use a different
+ * strictness setting create a {@link JsonReader}, call its {@link JsonReader#setStrictness(Strictness)}
+ * method and then use {@link #read(JsonReader)} for reading.
*
* No exception is thrown if the JSON data has multiple top-level JSON elements,
* or if there is trailing data.
@@ -270,10 +271,10 @@ public final T fromJson(Reader in) throws IOException {
}
/**
- * Converts the JSON document in {@code json} to a Java object. Unlike Gson's
- * similar {@link Gson#fromJson(String, Class) fromJson} method, this read is
- * strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code
- * JsonReader} and call {@link #read(JsonReader)} for lenient reading.
+ * Converts the JSON document in {@code json} to a Java object. The strictness
+ * {@link Strictness#LEGACY_STRICT} is used for reading the JSON data. To use a different
+ * strictness setting create a {@link JsonReader}, call its {@link JsonReader#setStrictness(Strictness)}
+ * method and then use {@link #read(JsonReader)} for reading.
*
*
No exception is thrown if the JSON data has multiple top-level JSON elements,
* or if there is trailing data.
diff --git a/gson/src/main/java/com/google/gson/reflect/TypeToken.java b/gson/src/main/java/com/google/gson/reflect/TypeToken.java
index 4a695666c8..3921a70b64 100644
--- a/gson/src/main/java/com/google/gson/reflect/TypeToken.java
+++ b/gson/src/main/java/com/google/gson/reflect/TypeToken.java
@@ -337,9 +337,12 @@ public static TypeToken get(Class type) {
* As seen here the result is a {@code TypeToken>}; this method cannot provide any type safety,
* and care must be taken to pass in the correct number of type arguments.
*
+ * If {@code rawType} is a non-generic class and no type arguments are provided, this method
+ * simply delegates to {@link #get(Class)} and creates a {@code TypeToken(Class)}.
+ *
* @throws IllegalArgumentException
- * If {@code rawType} is not of type {@code Class}, if it is not a generic type, or if the
- * type arguments are invalid for the raw type
+ * If {@code rawType} is not of type {@code Class}, or if the type arguments are invalid for
+ * the raw type
*/
public static TypeToken> getParameterized(Type rawType, Type... typeArguments) {
Objects.requireNonNull(rawType);
@@ -354,10 +357,16 @@ public static TypeToken> getParameterized(Type rawType, Type... typeArguments)
Class> rawClass = (Class>) rawType;
TypeVariable>[] typeVariables = rawClass.getTypeParameters();
- // Note: Does not check if owner type of rawType is generic because this factory method
- // does not support specifying owner type
- if (typeVariables.length == 0) {
- throw new IllegalArgumentException(rawClass.getName() + " is not a generic type");
+ int expectedArgsCount = typeVariables.length;
+ int actualArgsCount = typeArguments.length;
+ if (actualArgsCount != expectedArgsCount) {
+ throw new IllegalArgumentException(rawClass.getName() + " requires " + expectedArgsCount +
+ " type arguments, but got " + actualArgsCount);
+ }
+
+ // For legacy reasons create a TypeToken(Class) if the type is not generic
+ if (typeArguments.length == 0) {
+ return get(rawClass);
}
// Check for this here to avoid misleading exception thrown by ParameterizedTypeImpl
@@ -366,13 +375,6 @@ public static TypeToken> getParameterized(Type rawType, Type... typeArguments)
+ " it requires specifying an owner type");
}
- int expectedArgsCount = typeVariables.length;
- int actualArgsCount = typeArguments.length;
- if (actualArgsCount != expectedArgsCount) {
- throw new IllegalArgumentException(rawClass.getName() + " requires " + expectedArgsCount +
- " type arguments, but got " + actualArgsCount);
- }
-
for (int i = 0; i < expectedArgsCount; i++) {
Type typeArgument = Objects.requireNonNull(typeArguments[i], "Type argument must not be null");
Class> rawTypeArgument = $Gson$Types.getRawType(typeArgument);
diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java
index de7aef5ff5..0d106a1ccc 100644
--- a/gson/src/main/java/com/google/gson/stream/JsonReader.java
+++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java
@@ -16,6 +16,7 @@
package com.google.gson.stream;
+import com.google.gson.Strictness;
import com.google.gson.internal.JsonReaderInternalAccess;
import com.google.gson.internal.TroubleshootingGuide;
import com.google.gson.internal.bind.JsonTreeReader;
@@ -27,7 +28,7 @@
import java.util.Objects;
/**
- * Reads a JSON (RFC 7159 )
+ * Reads a JSON (RFC 8259 )
* encoded value as a stream of tokens. This stream includes both literal
* values (strings, numbers, booleans, and nulls) as well as the begin and
* end delimiters of objects and arrays. The tokens are traversed in
@@ -181,7 +182,7 @@
*
Prefixing JSON files with ")]}'\n"
makes them non-executable
* by {@code