diff --git a/gson/pom.xml b/gson/pom.xml
index 7918efc65d..ec08dfcda9 100644
--- a/gson/pom.xml
+++ b/gson/pom.xml
@@ -53,6 +53,12 @@
2.47.0
+
+ org.jspecify
+ jspecify
+ compile
+
+
junit
junit
diff --git a/gson/src/main/java/com/google/gson/FieldAttributes.java b/gson/src/main/java/com/google/gson/FieldAttributes.java
index b4d3709fb0..5cf0a165cb 100644
--- a/gson/src/main/java/com/google/gson/FieldAttributes.java
+++ b/gson/src/main/java/com/google/gson/FieldAttributes.java
@@ -22,6 +22,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
+import org.jspecify.annotations.Nullable;
/**
* A data object that stores attributes of a field.
@@ -113,7 +114,7 @@ public Class> getDeclaredClass() {
* @param annotation the class of the annotation that will be retrieved
* @return the annotation instance if it is bound to the field; otherwise {@code null}
*/
- public T getAnnotation(Class annotation) {
+ public @Nullable T getAnnotation(Class annotation) {
return field.getAnnotation(annotation);
}
diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java
index a06f290747..52b3c2893b 100644
--- a/gson/src/main/java/com/google/gson/Gson.java
+++ b/gson/src/main/java/com/google/gson/Gson.java
@@ -45,6 +45,7 @@
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.jspecify.annotations.Nullable;
/**
* This is the main class for using Gson. Gson is typically used by first constructing a Gson
@@ -148,7 +149,7 @@ public final class Gson {
* TypeAdapter} as value.
*/
@SuppressWarnings("ThreadLocalUsage")
- private final ThreadLocal, TypeAdapter>>> threadLocalAdapterResults =
+ private final ThreadLocal<@Nullable Map, TypeAdapter>>> threadLocalAdapterResults =
new ThreadLocal<>();
private final ConcurrentMap, TypeAdapter>> typeTokenCache =
@@ -167,7 +168,7 @@ public final class Gson {
final boolean generateNonExecutableJson;
final boolean htmlSafe;
final FormattingStyle formattingStyle;
- final Strictness strictness;
+ final @Nullable Strictness strictness;
final boolean serializeSpecialFloatingPointValues;
final boolean useJdkUnsafe;
final String datePattern;
@@ -493,7 +494,7 @@ public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeTo
* @since 1.4
* @see #toJsonTree(Object, Type)
*/
- public JsonElement toJsonTree(Object src) {
+ public JsonElement toJsonTree(@Nullable Object src) {
if (src == null) {
return JsonNull.INSTANCE;
}
@@ -518,7 +519,7 @@ public JsonElement toJsonTree(Object src) {
* @since 1.4
* @see #toJsonTree(Object)
*/
- public JsonElement toJsonTree(Object src, Type typeOfSrc) {
+ public JsonElement toJsonTree(@Nullable Object src, Type typeOfSrc) {
JsonTreeWriter writer = new JsonTreeWriter();
toJson(src, typeOfSrc, writer);
return writer.get();
@@ -539,7 +540,7 @@ public JsonElement toJsonTree(Object src, Type typeOfSrc) {
* @see #toJson(Object, Appendable)
* @see #toJson(Object, Type)
*/
- public String toJson(Object src) {
+ public String toJson(@Nullable Object src) {
if (src == null) {
return toJson(JsonNull.INSTANCE);
}
@@ -564,7 +565,7 @@ public String toJson(Object src) {
* @see #toJson(Object, Type, Appendable)
* @see #toJson(Object)
*/
- public String toJson(Object src, Type typeOfSrc) {
+ public String toJson(@Nullable Object src, Type typeOfSrc) {
StringBuilder writer = new StringBuilder();
toJson(src, typeOfSrc, writer);
return writer.toString();
@@ -586,7 +587,7 @@ public String toJson(Object src, Type typeOfSrc) {
* @see #toJson(Object)
* @see #toJson(Object, Type, Appendable)
*/
- public void toJson(Object src, Appendable writer) throws JsonIOException {
+ public void toJson(@Nullable Object src, Appendable writer) throws JsonIOException {
if (src != null) {
toJson(src, src.getClass(), writer);
} else {
@@ -614,7 +615,8 @@ public void toJson(Object src, Appendable writer) throws JsonIOException {
* @see #toJson(Object, Type)
* @see #toJson(Object, Appendable)
*/
- public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
+ public void toJson(@Nullable Object src, Type typeOfSrc, Appendable writer)
+ throws JsonIOException {
try {
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
toJson(src, typeOfSrc, jsonWriter);
@@ -644,7 +646,8 @@ public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOE
* @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 {
+ public void toJson(@Nullable Object src, Type typeOfSrc, JsonWriter writer)
+ throws JsonIOException {
@SuppressWarnings("unchecked")
TypeAdapter adapter = (TypeAdapter) getAdapter(TypeToken.get(typeOfSrc));
@@ -682,7 +685,7 @@ public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOE
* @return JSON String representation of the tree.
* @since 1.4
*/
- public String toJson(JsonElement jsonElement) {
+ public String toJson(@Nullable JsonElement jsonElement) {
StringBuilder writer = new StringBuilder();
toJson(jsonElement, writer);
return writer.toString();
@@ -696,7 +699,7 @@ public String toJson(JsonElement jsonElement) {
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.4
*/
- public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
+ public void toJson(@Nullable JsonElement jsonElement, Appendable writer) throws JsonIOException {
try {
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
toJson(jsonElement, jsonWriter);
@@ -725,7 +728,7 @@ public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOExce
* @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 {
+ public void toJson(@Nullable JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
Strictness oldStrictness = writer.getStrictness();
boolean oldHtmlSafe = writer.isHtmlSafe();
boolean oldSerializeNulls = writer.getSerializeNulls();
@@ -824,7 +827,8 @@ public JsonReader newJsonReader(Reader reader) {
* @see #fromJson(Reader, Class)
* @see #fromJson(String, TypeToken)
*/
- public T fromJson(String json, Class classOfT) throws JsonSyntaxException {
+ public @Nullable T fromJson(@Nullable String json, Class classOfT)
+ throws JsonSyntaxException {
return fromJson(json, TypeToken.get(classOfT));
}
@@ -853,7 +857,7 @@ public T fromJson(String json, Class classOfT) throws JsonSyntaxException
* @see #fromJson(String, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
- public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
+ public @Nullable T fromJson(@Nullable String json, Type typeOfT) throws JsonSyntaxException {
return (T) fromJson(json, TypeToken.get(typeOfT));
}
@@ -883,7 +887,8 @@ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
* @see #fromJson(String, Class)
* @since 2.10
*/
- public T fromJson(String json, TypeToken typeOfT) throws JsonSyntaxException {
+ public @Nullable T fromJson(@Nullable String json, TypeToken typeOfT)
+ throws JsonSyntaxException {
if (json == null) {
return null;
}
@@ -914,7 +919,7 @@ public T fromJson(String json, TypeToken typeOfT) throws JsonSyntaxExcept
* @see #fromJson(String, Class)
* @see #fromJson(Reader, TypeToken)
*/
- public T fromJson(Reader json, Class classOfT)
+ public @Nullable T fromJson(Reader json, Class classOfT)
throws JsonSyntaxException, JsonIOException {
return fromJson(json, TypeToken.get(classOfT));
}
@@ -945,7 +950,8 @@ public T fromJson(Reader json, Class classOfT)
* @see #fromJson(Reader, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
- public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
+ public @Nullable T fromJson(Reader json, Type typeOfT)
+ throws JsonIOException, JsonSyntaxException {
return (T) fromJson(json, TypeToken.get(typeOfT));
}
@@ -975,7 +981,7 @@ public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyn
* @see #fromJson(Reader, Class)
* @since 2.10
*/
- public T fromJson(Reader json, TypeToken typeOfT)
+ public @Nullable T fromJson(Reader json, TypeToken typeOfT)
throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = newJsonReader(json);
T object = fromJson(jsonReader, typeOfT);
@@ -1020,7 +1026,7 @@ public T fromJson(Reader json, TypeToken typeOfT)
* @see #fromJson(JsonReader, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
- public T fromJson(JsonReader reader, Type typeOfT)
+ public @Nullable T fromJson(JsonReader reader, Type typeOfT)
throws JsonIOException, JsonSyntaxException {
return (T) fromJson(reader, TypeToken.get(typeOfT));
}
@@ -1061,7 +1067,7 @@ public T fromJson(JsonReader reader, Type typeOfT)
* @see #fromJson(JsonReader, Type)
* @since 2.10
*/
- public T fromJson(JsonReader reader, TypeToken typeOfT)
+ public @Nullable T fromJson(JsonReader reader, TypeToken typeOfT)
throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
Strictness oldStrictness = reader.getStrictness();
@@ -1133,7 +1139,8 @@ public T fromJson(JsonReader reader, TypeToken typeOfT)
* @see #fromJson(Reader, Class)
* @see #fromJson(JsonElement, TypeToken)
*/
- public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException {
+ public @Nullable T fromJson(@Nullable JsonElement json, Class classOfT)
+ throws JsonSyntaxException {
return fromJson(json, TypeToken.get(classOfT));
}
@@ -1160,7 +1167,8 @@ public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxExce
* @see #fromJson(JsonElement, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
- public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
+ public @Nullable T fromJson(@Nullable JsonElement json, Type typeOfT)
+ throws JsonSyntaxException {
return (T) fromJson(json, TypeToken.get(typeOfT));
}
@@ -1186,14 +1194,15 @@ public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException
* @see #fromJson(JsonElement, Class)
* @since 2.10
*/
- public T fromJson(JsonElement json, TypeToken typeOfT) throws JsonSyntaxException {
+ public @Nullable T fromJson(@Nullable JsonElement json, TypeToken typeOfT)
+ throws JsonSyntaxException {
if (json == null) {
return null;
}
return fromJson(new JsonTreeReader(json), typeOfT);
}
- private static void assertFullConsumption(Object obj, JsonReader reader) {
+ private static void assertFullConsumption(@Nullable Object obj, JsonReader reader) {
try {
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonSyntaxException("JSON document was not fully consumed.");
@@ -1214,7 +1223,7 @@ private static void assertFullConsumption(Object obj, JsonReader reader) {
* @see Gson#threadLocalAdapterResults
*/
static class FutureTypeAdapter extends SerializationDelegatingTypeAdapter {
- private TypeAdapter delegate = null;
+ private @Nullable TypeAdapter delegate = null;
public void setDelegate(TypeAdapter typeAdapter) {
if (delegate != null) {
diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java
index df2c4acb8e..478e27b3a0 100644
--- a/gson/src/main/java/com/google/gson/GsonBuilder.java
+++ b/gson/src/main/java/com/google/gson/GsonBuilder.java
@@ -51,6 +51,7 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
+import org.jspecify.annotations.Nullable;
/**
* Use this builder to construct a {@link Gson} instance when you need to set configuration options
@@ -92,14 +93,14 @@
public final class GsonBuilder {
private static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
// Strictness of `null` is the legacy mode where some Gson APIs are always lenient
- private static final Strictness DEFAULT_STRICTNESS = null;
+ private static final @Nullable Strictness DEFAULT_STRICTNESS = null;
private static final FormattingStyle DEFAULT_FORMATTING_STYLE = FormattingStyle.COMPACT;
private static final boolean DEFAULT_ESCAPE_HTML = true;
private static final boolean DEFAULT_SERIALIZE_NULLS = false;
private static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
private static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
private static final boolean DEFAULT_USE_JDK_UNSAFE = true;
- private static final String DEFAULT_DATE_PATTERN = null;
+ private static final @Nullable String DEFAULT_DATE_PATTERN = null;
private static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY =
FieldNamingPolicy.IDENTITY;
private static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE;
@@ -135,7 +136,7 @@ public final class GsonBuilder {
final List hierarchyFactories = new ArrayList<>();
boolean serializeNulls = DEFAULT_SERIALIZE_NULLS;
- String datePattern = DEFAULT_DATE_PATTERN;
+ @Nullable String datePattern = DEFAULT_DATE_PATTERN;
int dateStyle = DateFormat.DEFAULT;
int timeStyle = DateFormat.DEFAULT;
boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS;
@@ -143,7 +144,7 @@ public final class GsonBuilder {
boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML;
FormattingStyle formattingStyle = DEFAULT_FORMATTING_STYLE;
boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
- Strictness strictness = DEFAULT_STRICTNESS;
+ @Nullable Strictness strictness = DEFAULT_STRICTNESS;
boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
@@ -635,7 +636,7 @@ public GsonBuilder disableHtmlEscaping() {
* @since 1.2
*/
@CanIgnoreReturnValue
- public GsonBuilder setDateFormat(String pattern) {
+ public GsonBuilder setDateFormat(@Nullable String pattern) {
if (pattern != null) {
try {
SimpleDateFormat unused = new SimpleDateFormat(pattern);
diff --git a/gson/src/main/java/com/google/gson/JsonArray.java b/gson/src/main/java/com/google/gson/JsonArray.java
index 10b94c0dc1..8402093d31 100644
--- a/gson/src/main/java/com/google/gson/JsonArray.java
+++ b/gson/src/main/java/com/google/gson/JsonArray.java
@@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import org.jspecify.annotations.Nullable;
/**
* A class representing an array type in JSON. An array is a list of {@link JsonElement}s each of
@@ -83,7 +84,7 @@ public JsonArray deepCopy() {
* @param bool the boolean that needs to be added to the array.
* @since 2.4
*/
- public void add(Boolean bool) {
+ public void add(@Nullable Boolean bool) {
elements.add(bool == null ? JsonNull.INSTANCE : new JsonPrimitive(bool));
}
@@ -93,7 +94,7 @@ public void add(Boolean bool) {
* @param character the character that needs to be added to the array.
* @since 2.4
*/
- public void add(Character character) {
+ public void add(@Nullable Character character) {
elements.add(character == null ? JsonNull.INSTANCE : new JsonPrimitive(character));
}
@@ -103,7 +104,7 @@ public void add(Character character) {
* @param number the number that needs to be added to the array.
* @since 2.4
*/
- public void add(Number number) {
+ public void add(@Nullable Number number) {
elements.add(number == null ? JsonNull.INSTANCE : new JsonPrimitive(number));
}
@@ -113,7 +114,7 @@ public void add(Number number) {
* @param string the string that needs to be added to the array.
* @since 2.4
*/
- public void add(String string) {
+ public void add(@Nullable String string) {
elements.add(string == null ? JsonNull.INSTANCE : new JsonPrimitive(string));
}
@@ -122,7 +123,7 @@ public void add(String string) {
*
* @param element the element that needs to be added to the array.
*/
- public void add(JsonElement element) {
+ public void add(@Nullable JsonElement element) {
if (element == null) {
element = JsonNull.INSTANCE;
}
@@ -147,7 +148,7 @@ public void addAll(JsonArray array) {
* @throws IndexOutOfBoundsException if the specified index is outside the array bounds
*/
@CanIgnoreReturnValue
- public JsonElement set(int index, JsonElement element) {
+ public JsonElement set(int index, @Nullable JsonElement element) {
return elements.set(index, element == null ? JsonNull.INSTANCE : element);
}
diff --git a/gson/src/main/java/com/google/gson/JsonObject.java b/gson/src/main/java/com/google/gson/JsonObject.java
index 3bde741190..a64cba1688 100644
--- a/gson/src/main/java/com/google/gson/JsonObject.java
+++ b/gson/src/main/java/com/google/gson/JsonObject.java
@@ -20,6 +20,7 @@
import com.google.gson.internal.LinkedTreeMap;
import java.util.Map;
import java.util.Set;
+import org.jspecify.annotations.Nullable;
/**
* A class representing an object type in JSON. An object consists of name-value pairs where names
@@ -66,7 +67,7 @@ public JsonObject deepCopy() {
* @param property name of the member.
* @param value the member object.
*/
- public void add(String property, JsonElement value) {
+ public void add(String property, @Nullable JsonElement value) {
members.put(property, value == null ? JsonNull.INSTANCE : value);
}
@@ -79,7 +80,7 @@ public void add(String property, JsonElement value) {
* @since 1.3
*/
@CanIgnoreReturnValue
- public JsonElement remove(String property) {
+ public @Nullable JsonElement remove(String property) {
return members.remove(property);
}
@@ -90,7 +91,7 @@ public JsonElement remove(String property) {
* @param property name of the member.
* @param value the string value associated with the member.
*/
- public void addProperty(String property, String value) {
+ public void addProperty(String property, @Nullable String value) {
add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
}
@@ -101,7 +102,7 @@ public void addProperty(String property, String value) {
* @param property name of the member.
* @param value the number value associated with the member.
*/
- public void addProperty(String property, Number value) {
+ public void addProperty(String property, @Nullable Number value) {
add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
}
@@ -112,7 +113,7 @@ public void addProperty(String property, Number value) {
* @param property name of the member.
* @param value the boolean value associated with the member.
*/
- public void addProperty(String property, Boolean value) {
+ public void addProperty(String property, @Nullable Boolean value) {
add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
}
@@ -123,7 +124,7 @@ public void addProperty(String property, Boolean value) {
* @param property name of the member.
* @param value the char value associated with the member.
*/
- public void addProperty(String property, Character value) {
+ public void addProperty(String property, @Nullable Character value) {
add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
}
@@ -183,7 +184,7 @@ public boolean has(String memberName) {
* @param memberName name of the member that is being requested.
* @return the member matching the name, or {@code null} if no such member exists.
*/
- public JsonElement get(String memberName) {
+ public @Nullable JsonElement get(String memberName) {
return members.get(memberName);
}
@@ -195,7 +196,7 @@ public JsonElement get(String memberName) {
* member with this name exists.
* @throws ClassCastException if the member is not of type {@code JsonPrimitive}.
*/
- public JsonPrimitive getAsJsonPrimitive(String memberName) {
+ public @Nullable JsonPrimitive getAsJsonPrimitive(String memberName) {
return (JsonPrimitive) members.get(memberName);
}
@@ -207,7 +208,7 @@ public JsonPrimitive getAsJsonPrimitive(String memberName) {
* member with this name exists.
* @throws ClassCastException if the member is not of type {@code JsonArray}.
*/
- public JsonArray getAsJsonArray(String memberName) {
+ public @Nullable JsonArray getAsJsonArray(String memberName) {
return (JsonArray) members.get(memberName);
}
@@ -219,7 +220,7 @@ public JsonArray getAsJsonArray(String memberName) {
* member with this name exists.
* @throws ClassCastException if the member is not of type {@code JsonObject}.
*/
- public JsonObject getAsJsonObject(String memberName) {
+ public @Nullable JsonObject getAsJsonObject(String memberName) {
return (JsonObject) members.get(memberName);
}
diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java
index e33a839dbd..9337c6cddd 100644
--- a/gson/src/main/java/com/google/gson/TypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/TypeAdapter.java
@@ -26,6 +26,7 @@
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
+import org.jspecify.annotations.Nullable;
/**
* Converts Java objects to and from JSON.
@@ -127,7 +128,7 @@ public TypeAdapter() {}
*
* @param value the Java object to write. May be null.
*/
- public abstract void write(JsonWriter out, T value) throws IOException;
+ public abstract void write(JsonWriter out, @Nullable T value) throws IOException;
/**
* Converts {@code value} to a JSON document and writes it to {@code out}.
@@ -191,7 +192,7 @@ public final JsonElement toJsonTree(T value) {
*
* @return the converted Java object. May be {@code null}.
*/
- public abstract T read(JsonReader in) throws IOException;
+ public abstract @Nullable T read(JsonReader in) throws IOException;
/**
* Converts the JSON document in {@code in} to a Java object.
@@ -238,7 +239,7 @@ public final T fromJson(String json) throws IOException {
* @throws JsonIOException wrapping {@code IOException}s thrown by {@link #read(JsonReader)}
* @since 2.2
*/
- public final T fromJsonTree(JsonElement jsonTree) {
+ public final T fromJsonTree(@Nullable JsonElement jsonTree) {
try {
JsonReader jsonReader = new JsonTreeReader(jsonTree);
return read(jsonReader);
@@ -297,7 +298,7 @@ public final TypeAdapter nullSafe() {
private final class NullSafeTypeAdapter extends TypeAdapter {
@Override
- public void write(JsonWriter out, T value) throws IOException {
+ public void write(JsonWriter out, @Nullable T value) throws IOException {
if (value == null) {
out.nullValue();
} else {
@@ -306,7 +307,7 @@ public void write(JsonWriter out, T value) throws IOException {
}
@Override
- public T read(JsonReader reader) throws IOException {
+ public @Nullable T read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
diff --git a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java
index 4473e59b7a..08141f8cb5 100644
--- a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java
+++ b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java
@@ -17,6 +17,7 @@
package com.google.gson;
import com.google.gson.reflect.TypeToken;
+import org.jspecify.annotations.Nullable;
/**
* Creates type adapters for set of related types. Type adapter factories are most useful when
@@ -166,5 +167,5 @@ public interface TypeAdapterFactory {
/**
* Returns a type adapter for {@code type}, or null if this factory doesn't support {@code type}.
*/
- TypeAdapter create(Gson gson, TypeToken type);
+ @Nullable TypeAdapter create(Gson gson, TypeToken type);
}
diff --git a/gson/src/main/java/com/google/gson/annotations/package-info.java b/gson/src/main/java/com/google/gson/annotations/package-info.java
index edc5304c4b..4e27a711eb 100644
--- a/gson/src/main/java/com/google/gson/annotations/package-info.java
+++ b/gson/src/main/java/com/google/gson/annotations/package-info.java
@@ -19,5 +19,6 @@
*
* @author Inderjeet Singh, Joel Leitch
*/
+@org.jspecify.annotations.NullMarked
@com.google.errorprone.annotations.CheckReturnValue
package com.google.gson.annotations;
diff --git a/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java b/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java
index ead949ae1e..efbe0a9106 100644
--- a/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java
+++ b/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java
@@ -21,6 +21,7 @@
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;
+import org.jspecify.annotations.Nullable;
/** Internal helper class for {@link ReflectionAccessFilter}. */
public class ReflectionAccessFilterHelper {
@@ -73,7 +74,7 @@ public static FilterResult getFilterResult(
}
/** See {@link AccessibleObject#canAccess(Object)} (Java >= 9) */
- public static boolean canAccess(AccessibleObject accessibleObject, Object object) {
+ public static boolean canAccess(AccessibleObject accessibleObject, @Nullable Object object) {
return AccessChecker.INSTANCE.canAccess(accessibleObject, object);
}
@@ -90,7 +91,8 @@ private abstract static class AccessChecker {
accessChecker =
new AccessChecker() {
@Override
- public boolean canAccess(AccessibleObject accessibleObject, Object object) {
+ public boolean canAccess(
+ AccessibleObject accessibleObject, @Nullable Object object) {
try {
return (Boolean) canAccessMethod.invoke(accessibleObject, object);
} catch (Exception e) {
@@ -107,7 +109,7 @@ public boolean canAccess(AccessibleObject accessibleObject, Object object) {
accessChecker =
new AccessChecker() {
@Override
- public boolean canAccess(AccessibleObject accessibleObject, Object object) {
+ public boolean canAccess(AccessibleObject accessibleObject, @Nullable Object object) {
// Cannot determine whether object can be accessed, so assume it can be accessed
return true;
}
@@ -116,6 +118,6 @@ public boolean canAccess(AccessibleObject accessibleObject, Object object) {
INSTANCE = accessChecker;
}
- abstract boolean canAccess(AccessibleObject accessibleObject, Object object);
+ abstract boolean canAccess(AccessibleObject accessibleObject, @Nullable Object object);
}
}
diff --git a/gson/src/main/java/com/google/gson/internal/Streams.java b/gson/src/main/java/com/google/gson/internal/Streams.java
index 12b8be86ee..cf4402e5b7 100644
--- a/gson/src/main/java/com/google/gson/internal/Streams.java
+++ b/gson/src/main/java/com/google/gson/internal/Streams.java
@@ -32,6 +32,7 @@
import java.io.IOException;
import java.io.Writer;
import java.util.Objects;
+import org.jspecify.annotations.Nullable;
/** Reads and writes GSON parse trees over streams. */
public final class Streams {
@@ -66,7 +67,7 @@ public static JsonElement parse(JsonReader reader) throws JsonParseException {
}
/** Writes the JSON element to the writer, recursively. */
- public static void write(JsonElement element, JsonWriter writer) throws IOException {
+ public static void write(@Nullable JsonElement element, JsonWriter writer) throws IOException {
JsonElementTypeAdapter.ADAPTER.write(writer, element);
}
@@ -133,8 +134,8 @@ public Writer append(CharSequence csq, int start, int end) throws IOException {
/** A mutable char sequence pointing at a single char[]. */
private static class CurrentWrite implements CharSequence {
- private char[] chars;
- private String cachedString;
+ private char @Nullable [] chars;
+ private @Nullable String cachedString;
void setChars(char[] chars) {
this.chars = chars;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java
index 50efa418c0..8675fa69e4 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java
@@ -29,13 +29,14 @@
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.ArrayList;
+import org.jspecify.annotations.Nullable;
/** Adapter for arrays. */
public final class ArrayTypeAdapter extends TypeAdapter {
public static final TypeAdapterFactory FACTORY =
new TypeAdapterFactory() {
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Type type = typeToken.getType();
if (!(type instanceof GenericArrayType
|| (type instanceof Class && ((Class>) type).isArray()))) {
@@ -63,13 +64,13 @@ public ArrayTypeAdapter(
}
@Override
- public Object read(JsonReader in) throws IOException {
+ public @Nullable Object read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
- ArrayList list = new ArrayList<>();
+ ArrayList<@Nullable E> list = new ArrayList<>();
in.beginArray();
while (in.hasNext()) {
E instance = componentTypeAdapter.read(in);
@@ -95,7 +96,7 @@ public Object read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, Object array) throws IOException {
+ public void write(JsonWriter out, @Nullable Object array) throws IOException {
if (array == null) {
out.nullValue();
return;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java
index 7dd48a3ebb..b377f0d47e 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collection;
+import org.jspecify.annotations.Nullable;
/** Adapt a homogeneous collection of objects. */
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
@@ -39,7 +40,7 @@ public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructo
}
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Type type = typeToken.getType();
Class super T> rawType = typeToken.getRawType();
@@ -72,13 +73,13 @@ private static final class Adapter extends TypeAdapter> {
}
@Override
- public Collection read(JsonReader in) throws IOException {
+ public @Nullable Collection<@Nullable E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
- Collection collection = constructor.construct();
+ Collection<@Nullable E> collection = constructor.construct();
in.beginArray();
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
@@ -89,7 +90,7 @@ public Collection read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, Collection collection) throws IOException {
+ public void write(JsonWriter out, @Nullable Collection collection) throws IOException {
if (collection == null) {
out.nullValue();
return;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java
index b5dffe24fb..5c900fbf3b 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java
@@ -38,6 +38,7 @@
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
+import org.jspecify.annotations.Nullable;
/**
* This type adapter supports subclasses of date by defining a {@link
@@ -65,7 +66,7 @@ public final class DefaultDateTypeAdapter extends TypeAdapter
new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
return typeToken.getRawType() == Date.class
? (TypeAdapter)
new DefaultDateTypeAdapter<>(
diff --git a/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java
index b3dbb680c1..f7ffd95048 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java
@@ -30,13 +30,14 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
/** Adapter for enum classes (but not for the base class {@code java.lang.Enum}). */
class EnumTypeAdapter> extends TypeAdapter {
static final TypeAdapterFactory FACTORY =
new TypeAdapterFactory() {
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Class super T> rawType = typeToken.getRawType();
if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
return null;
@@ -111,7 +112,7 @@ private EnumTypeAdapter(Class classOfT) {
}
@Override
- public T read(JsonReader in) throws IOException {
+ public @Nullable T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
@@ -123,7 +124,7 @@ public T read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, T value) throws IOException {
+ public void write(JsonWriter out, @Nullable T value) throws IOException {
out.value(value == null ? null : constantToName.get(value));
}
}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java
index 791f15b44a..217939dfbc 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java
@@ -26,6 +26,7 @@
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
+import org.jspecify.annotations.Nullable;
/**
* Type adapters for {@code java.time} types.
@@ -393,7 +394,7 @@ public void write(JsonWriter out, ZonedDateTime value) throws IOException {
static final TypeAdapterFactory JAVA_TIME_FACTORY =
new TypeAdapterFactory() {
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Class super T> rawType = typeToken.getRawType();
if (!rawType.getName().startsWith("java.time.")) {
// Immediately return null so we don't load all these classes when nobody's doing
diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java
index 193ab8f7a6..f56cc933ba 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java
@@ -27,6 +27,7 @@
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.jspecify.annotations.Nullable;
/**
* Given a type T, looks for the annotation {@link JsonAdapter} and uses an instance of the
@@ -37,7 +38,7 @@
public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory {
private static class DummyTypeAdapterFactory implements TypeAdapterFactory {
@Override
- public TypeAdapter create(Gson gson, TypeToken type) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken type) {
throw new AssertionError("Factory should not be used");
}
}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java
index 6590dcff1b..51723541d9 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java
@@ -30,6 +30,7 @@
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
/** Adapter for {@link JsonElement} and subclasses. */
public class JsonElementTypeAdapter extends TypeAdapter {
@@ -41,7 +42,8 @@ private JsonElementTypeAdapter() {}
* Tries to begin reading a JSON array or JSON object, returning {@code null} if the next element
* is neither of those.
*/
- private JsonElement tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException {
+ private @Nullable JsonElement tryBeginNesting(JsonReader in, JsonToken peeked)
+ throws IOException {
switch (peeked) {
case BEGIN_ARRAY:
in.beginArray();
@@ -136,7 +138,7 @@ public JsonElement read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, JsonElement value) throws IOException {
+ public void write(JsonWriter out, @Nullable JsonElement value) throws IOException {
if (value == null || value.isJsonNull()) {
out.nullValue();
} else if (value.isJsonPrimitive()) {
diff --git a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java
index 49fc731edf..8f6b10a388 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java
@@ -36,6 +36,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
/**
* Adapts maps to either JSON objects or JSON arrays.
@@ -123,7 +124,7 @@ public MapTypeAdapterFactory(
}
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Type type = typeToken.getType();
Class super T> rawType = typeToken.getRawType();
@@ -173,7 +174,7 @@ private final class Adapter extends TypeAdapter> {
}
@Override
- public Map read(JsonReader in) throws IOException {
+ public @Nullable Map read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
@@ -212,7 +213,7 @@ public Map read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, Map map) throws IOException {
+ public void write(JsonWriter out, @Nullable Map map) throws IOException {
if (map == null) {
out.nullValue();
return;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java
index 80eabccd93..34de742940 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java
@@ -27,6 +27,7 @@
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
+import org.jspecify.annotations.Nullable;
/** Type adapter for {@link Number}. */
public final class NumberTypeAdapter extends TypeAdapter {
@@ -45,7 +46,7 @@ private static TypeAdapterFactory newFactory(ToNumberStrategy toNumberStrategy)
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
@Override
- public TypeAdapter create(Gson gson, TypeToken type) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken type) {
return type.getRawType() == Number.class ? (TypeAdapter) adapter : null;
}
};
@@ -60,7 +61,7 @@ public static TypeAdapterFactory getFactory(ToNumberStrategy toNumberStrategy) {
}
@Override
- public Number read(JsonReader in) throws IOException {
+ public @Nullable Number read(JsonReader in) throws IOException {
JsonToken jsonToken = in.peek();
switch (jsonToken) {
case NULL:
@@ -76,7 +77,7 @@ public Number read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, Number value) throws IOException {
+ public void write(JsonWriter out, @Nullable Number value) throws IOException {
out.value(value);
}
}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java
index 2fa704544f..f36bdb01c7 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java
@@ -32,6 +32,7 @@
import java.util.Deque;
import java.util.List;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
/**
* Adapts types whose static type is only 'Object'. Uses getClass() on serialization and a
@@ -53,7 +54,7 @@ private static TypeAdapterFactory newFactory(ToNumberStrategy toNumberStrategy)
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
@Override
- public TypeAdapter create(Gson gson, TypeToken type) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken type) {
if (type.getRawType() == Object.class) {
return (TypeAdapter) new ObjectTypeAdapter(gson, toNumberStrategy);
}
@@ -74,7 +75,7 @@ public static TypeAdapterFactory getFactory(ToNumberStrategy toNumberStrategy) {
* Tries to begin reading a JSON array or JSON object, returning {@code null} if the next element
* is neither of those.
*/
- private Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException {
+ private @Nullable Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException {
switch (peeked) {
case BEGIN_ARRAY:
in.beginArray();
@@ -88,7 +89,7 @@ private Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOExcepti
}
/** Reads an {@code Object} which cannot have any nested elements */
- private Object readTerminal(JsonReader in, JsonToken peeked) throws IOException {
+ private @Nullable Object readTerminal(JsonReader in, JsonToken peeked) throws IOException {
switch (peeked) {
case STRING:
return in.nextString();
@@ -167,7 +168,7 @@ public Object read(JsonReader in) throws IOException {
}
@Override
- public void write(JsonWriter out, Object value) throws IOException {
+ public void write(JsonWriter out, @Nullable Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java
index ef464684aa..5e2c433486 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java
@@ -55,6 +55,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
/** Type adapter that reflects over the fields and methods of a class. */
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
@@ -107,7 +108,7 @@ private List getFieldNames(Field f) {
}
@Override
- public TypeAdapter create(Gson gson, TypeToken type) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken type) {
Class super T> raw = type.getRawType();
if (!Object.class.isAssignableFrom(raw)) {
@@ -166,7 +167,7 @@ public String toString() {
}
private static void checkAccessible(
- Object object, M member) {
+ @Nullable Object object, M member) {
if (!ReflectionAccessFilterHelper.canAccess(
member, Modifier.isStatic(member.getModifiers()) ? null : object)) {
String memberDescription = ReflectionHelper.getAccessibleObjectDescription(member, true);
@@ -181,7 +182,7 @@ private static void checkAccessible(
private BoundField createBoundField(
Gson context,
Field field,
- Method accessor,
+ @Nullable Method accessor,
String serializedName,
TypeToken> fieldType,
boolean serialize,
@@ -252,7 +253,7 @@ void write(JsonWriter writer, Object source) throws IOException, IllegalAccessEx
}
@Override
- void readIntoArray(JsonReader reader, int index, Object[] target)
+ void readIntoArray(JsonReader reader, int index, @Nullable Object[] target)
throws IOException, JsonParseException {
Object fieldValue = typeAdapter.read(reader);
if (fieldValue == null && isPrimitive) {
@@ -479,7 +480,7 @@ public abstract static class Adapter extends TypeAdapter {
}
@Override
- public void write(JsonWriter out, T value) throws IOException {
+ public void write(JsonWriter out, @Nullable T value) throws IOException {
if (value == null) {
out.nullValue();
return;
diff --git a/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java
index 62ea14d383..8e74a4d824 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java
@@ -32,6 +32,7 @@
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Objects;
+import org.jspecify.annotations.Nullable;
/**
* Adapts a Gson 1.x tree-style adapter as a streaming TypeAdapter. Since the tree adapter may be
@@ -176,7 +177,7 @@ private static final class SingleTypeFactory implements TypeAdapterFactory {
@SuppressWarnings("unchecked") // guarded by typeToken.equals() call
@Override
- public TypeAdapter create(Gson gson, TypeToken type) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken type) {
boolean matches =
exactType != null
? exactType.equals(type) || (matchRawType && exactType.getType() == type.getRawType())
diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java
index 852ae56c5b..9da3b9b5a3 100644
--- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java
+++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java
@@ -52,6 +52,7 @@
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
+import org.jspecify.annotations.Nullable;
/**
* Type adapters for basic types. More complex adapters exist as separate classes in the enclosing
@@ -946,7 +947,7 @@ interface FactorySupplier {
TypeAdapterFactory get();
}
- public static TypeAdapterFactory javaTimeTypeAdapterFactory() {
+ public static @Nullable TypeAdapterFactory javaTimeTypeAdapterFactory() {
try {
Class> javaTimeTypeAdapterFactoryClass =
Class.forName("com.google.gson.internal.bind.JavaTimeTypeAdapters");
@@ -964,7 +965,7 @@ public static TypeAdapterFactory newFactory(
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
return typeToken.equals(type) ? (TypeAdapter) typeAdapter : null;
}
};
@@ -975,7 +976,7 @@ public static TypeAdapterFactory newFactory(Class type, TypeAdapter
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
return typeToken.getRawType() == type ? (TypeAdapter) typeAdapter : null;
}
@@ -992,7 +993,7 @@ public static TypeAdapterFactory newFactory(
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Class super T> rawType = typeToken.getRawType();
return (rawType == unboxed || rawType == boxed) ? (TypeAdapter) typeAdapter : null;
}
@@ -1016,7 +1017,7 @@ public static TypeAdapterFactory newFactoryForMultipleTypes(
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
Class super T> rawType = typeToken.getRawType();
return (rawType == base || rawType == sub) ? (TypeAdapter) typeAdapter : null;
}
diff --git a/gson/src/main/java/com/google/gson/internal/bind/package-info.java b/gson/src/main/java/com/google/gson/internal/bind/package-info.java
new file mode 100644
index 0000000000..b8929d0191
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/bind/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Internal type adapters and factories used by Gson. */
+@org.jspecify.annotations.NullMarked
+package com.google.gson.internal.bind;
diff --git a/gson/src/main/java/com/google/gson/internal/package-info.java b/gson/src/main/java/com/google/gson/internal/package-info.java
index c92c71de63..0308c84bed 100644
--- a/gson/src/main/java/com/google/gson/internal/package-info.java
+++ b/gson/src/main/java/com/google/gson/internal/package-info.java
@@ -20,5 +20,6 @@
*
* @author Inderjeet Singh, Joel Leitch, Jesse Wilson
*/
+@org.jspecify.annotations.NullMarked
@com.google.errorprone.annotations.CheckReturnValue
package com.google.gson.internal;
diff --git a/gson/src/main/java/com/google/gson/internal/reflect/package-info.java b/gson/src/main/java/com/google/gson/internal/reflect/package-info.java
new file mode 100644
index 0000000000..d4429ef4aa
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/reflect/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Reflection helpers used internally by Gson. */
+@org.jspecify.annotations.NullMarked
+package com.google.gson.internal.reflect;
diff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java
index 1991daefb0..a4fb3bf6d7 100644
--- a/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java
@@ -30,6 +30,7 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
+import org.jspecify.annotations.Nullable;
/**
* Adapter for java.sql.Date. Although this class appears stateless, it is not. DateFormat captures
@@ -42,7 +43,7 @@ final class SqlDateTypeAdapter extends TypeAdapter {
new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
return typeToken.getRawType() == java.sql.Date.class
? (TypeAdapter) new SqlDateTypeAdapter()
: null;
diff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java
index d63ae0677e..24c48e0153 100644
--- a/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java
@@ -31,6 +31,7 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
+import org.jspecify.annotations.Nullable;
/**
* Adapter for java.sql.Time. Although this class appears stateless, it is not. DateFormat captures
@@ -43,7 +44,7 @@ final class SqlTimeTypeAdapter extends TypeAdapter {
new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
return typeToken.getRawType() == Time.class
? (TypeAdapter) new SqlTimeTypeAdapter()
: null;
diff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlTimestampTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlTimestampTypeAdapter.java
index ab1cefe544..0f18249d70 100644
--- a/gson/src/main/java/com/google/gson/internal/sql/SqlTimestampTypeAdapter.java
+++ b/gson/src/main/java/com/google/gson/internal/sql/SqlTimestampTypeAdapter.java
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
+import org.jspecify.annotations.Nullable;
@SuppressWarnings("JavaUtilDate")
class SqlTimestampTypeAdapter extends TypeAdapter {
@@ -32,7 +33,7 @@ class SqlTimestampTypeAdapter extends TypeAdapter {
new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) {
if (typeToken.getRawType() == Timestamp.class) {
TypeAdapter dateTypeAdapter = gson.getAdapter(Date.class);
return (TypeAdapter) new SqlTimestampTypeAdapter(dateTypeAdapter);
diff --git a/gson/src/main/java/com/google/gson/internal/sql/package-info.java b/gson/src/main/java/com/google/gson/internal/sql/package-info.java
new file mode 100644
index 0000000000..4486de31d7
--- /dev/null
+++ b/gson/src/main/java/com/google/gson/internal/sql/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** SQL type adapters used by Gson when {@code java.sql} is available. */
+@org.jspecify.annotations.NullMarked
+package com.google.gson.internal.sql;
diff --git a/gson/src/main/java/com/google/gson/package-info.java b/gson/src/main/java/com/google/gson/package-info.java
index 04d56b2f14..313f8c8041 100644
--- a/gson/src/main/java/com/google/gson/package-info.java
+++ b/gson/src/main/java/com/google/gson/package-info.java
@@ -24,5 +24,6 @@
*
* @author Inderjeet Singh, Joel Leitch
*/
+@org.jspecify.annotations.NullMarked
@com.google.errorprone.annotations.CheckReturnValue
package com.google.gson;
diff --git a/gson/src/main/java/com/google/gson/reflect/package-info.java b/gson/src/main/java/com/google/gson/reflect/package-info.java
index ddfafdba08..3d59d4c9a3 100644
--- a/gson/src/main/java/com/google/gson/reflect/package-info.java
+++ b/gson/src/main/java/com/google/gson/reflect/package-info.java
@@ -19,5 +19,6 @@
*
* @author Inderjeet Singh, Joel Leitch
*/
+@org.jspecify.annotations.NullMarked
@com.google.errorprone.annotations.CheckReturnValue
package com.google.gson.reflect;
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 e908c79d85..ef66d3b5a2 100644
--- a/gson/src/main/java/com/google/gson/stream/JsonReader.java
+++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java
@@ -26,6 +26,7 @@
import java.io.Reader;
import java.util.Arrays;
import java.util.Objects;
+import org.jspecify.annotations.Nullable;
/**
* Reads a JSON (RFC 8259 ) encoded value as a
@@ -288,7 +289,7 @@ public class JsonReader implements Closeable {
* A peeked string that should be parsed on the next double, long or string. This is populated
* before a numeric value is parsed and used if that parsing fails.
*/
- private String peekedString;
+ private @Nullable String peekedString;
/** The nesting stack. Using a manual array rather than an ArrayList saves 20%. */
private int[] stack = new int[32];
@@ -307,7 +308,7 @@ public class JsonReader implements Closeable {
* that array. Otherwise the value is undefined, and we take advantage of that
* by incrementing pathIndices when doing so isn't useful.
*/
- private String[] pathNames = new String[32];
+ private @Nullable String[] pathNames = new String[32];
private int[] pathIndices = new int[32];
/** Creates a new instance that reads a JSON-encoded stream from {@code in}. */
diff --git a/gson/src/main/java/com/google/gson/stream/JsonWriter.java b/gson/src/main/java/com/google/gson/stream/JsonWriter.java
index f08a698240..a7c64fb237 100644
--- a/gson/src/main/java/com/google/gson/stream/JsonWriter.java
+++ b/gson/src/main/java/com/google/gson/stream/JsonWriter.java
@@ -38,6 +38,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
+import org.jspecify.annotations.Nullable;
/**
* Writes a JSON (RFC 8259 ) encoded value to a
@@ -175,8 +176,8 @@ public class JsonWriter implements Closeable, Flushable {
* newline characters. This prevents eval() from failing with a syntax
* error. http://code.google.com/p/google-gson/issues/detail?id=341
*/
- private static final String[] REPLACEMENT_CHARS;
- private static final String[] HTML_SAFE_REPLACEMENT_CHARS;
+ private static final @Nullable String[] REPLACEMENT_CHARS;
+ private static final @Nullable String[] HTML_SAFE_REPLACEMENT_CHARS;
static {
REPLACEMENT_CHARS = new String[128];
@@ -219,7 +220,7 @@ public class JsonWriter implements Closeable, Flushable {
private boolean htmlSafe;
- private String deferredName;
+ private @Nullable String deferredName;
private boolean serializeNulls = true;
@@ -524,7 +525,7 @@ private void writeDeferredName() throws IOException {
* @return this writer.
*/
@CanIgnoreReturnValue
- public JsonWriter value(String value) throws IOException {
+ public JsonWriter value(@Nullable String value) throws IOException {
if (value == null) {
return nullValue();
}
@@ -554,7 +555,7 @@ public JsonWriter value(boolean value) throws IOException {
* @since 2.7
*/
@CanIgnoreReturnValue
- public JsonWriter value(Boolean value) throws IOException {
+ public JsonWriter value(@Nullable Boolean value) throws IOException {
if (value == null) {
return nullValue();
}
@@ -630,7 +631,7 @@ public JsonWriter value(long value) throws IOException {
* JSON number.
*/
@CanIgnoreReturnValue
- public JsonWriter value(Number value) throws IOException {
+ public JsonWriter value(@Nullable Number value) throws IOException {
if (value == null) {
return nullValue();
}
@@ -689,7 +690,7 @@ public JsonWriter nullValue() throws IOException {
* @since 2.4
*/
@CanIgnoreReturnValue
- public JsonWriter jsonValue(String value) throws IOException {
+ public JsonWriter jsonValue(@Nullable String value) throws IOException {
if (value == null) {
return nullValue();
}
@@ -741,7 +742,7 @@ private static boolean alwaysCreatesValidJsonNumber(Class extends Number> c) {
}
private void string(String value) throws IOException {
- String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
+ @Nullable String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
out.write('\"');
int last = 0;
int length = value.length();
diff --git a/gson/src/main/java/com/google/gson/stream/package-info.java b/gson/src/main/java/com/google/gson/stream/package-info.java
index 84fbdbba58..f0c17fdf7a 100644
--- a/gson/src/main/java/com/google/gson/stream/package-info.java
+++ b/gson/src/main/java/com/google/gson/stream/package-info.java
@@ -15,5 +15,6 @@
*/
/** This package provides classes for processing JSON in an efficient streaming way. */
+@org.jspecify.annotations.NullMarked
@com.google.errorprone.annotations.CheckReturnValue
package com.google.gson.stream;
diff --git a/gson/src/main/java/module-info.java b/gson/src/main/java/module-info.java
index 6692639673..fc76bbc72b 100644
--- a/gson/src/main/java/module-info.java
+++ b/gson/src/main/java/module-info.java
@@ -20,6 +20,8 @@
* @since 2.8.6
*/
module com.google.gson {
+ requires static org.jspecify;
+
exports com.google.gson;
exports com.google.gson.annotations;
exports com.google.gson.reflect;
diff --git a/pom.xml b/pom.xml
index 7dfbc2aabc..1d4d944e3a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -87,6 +87,12 @@
4.13.2
+
+ org.jspecify
+ jspecify
+ 1.0.0
+
+
com.google.truth
truth