Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions gson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
<version>2.47.0</version>
</dependency>

<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
3 changes: 2 additions & 1 deletion gson/src/main/java/com/google/gson/FieldAttributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 extends Annotation> T getAnnotation(Class<T> annotation) {
public <T extends Annotation> @Nullable T getAnnotation(Class<T> annotation) {
return field.getAnnotation(annotation);
}

Expand Down
59 changes: 34 additions & 25 deletions gson/src/main/java/com/google/gson/Gson.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -148,7 +149,7 @@ public final class Gson {
* TypeAdapter} as value.
*/
@SuppressWarnings("ThreadLocalUsage")
private final ThreadLocal<Map<TypeToken<?>, TypeAdapter<?>>> threadLocalAdapterResults =
private final ThreadLocal<@Nullable Map<TypeToken<?>, TypeAdapter<?>>> threadLocalAdapterResults =
new ThreadLocal<>();

private final ConcurrentMap<TypeToken<?>, TypeAdapter<?>> typeTokenCache =
Expand All @@ -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;
Expand Down Expand Up @@ -493,7 +494,7 @@ public <T> TypeAdapter<T> 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;
}
Expand All @@ -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();
Expand All @@ -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);
}
Expand All @@ -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();
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<Object> adapter = (TypeAdapter<Object>) getAdapter(TypeToken.get(typeOfSrc));

Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -824,7 +827,8 @@ public JsonReader newJsonReader(Reader reader) {
* @see #fromJson(Reader, Class)
* @see #fromJson(String, TypeToken)
*/
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
public <T> @Nullable T fromJson(@Nullable String json, Class<T> classOfT)
throws JsonSyntaxException {
return fromJson(json, TypeToken.get(classOfT));
}

Expand Down Expand Up @@ -853,7 +857,7 @@ public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException
* @see #fromJson(String, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
public <T> @Nullable T fromJson(@Nullable String json, Type typeOfT) throws JsonSyntaxException {
return (T) fromJson(json, TypeToken.get(typeOfT));
}

Expand Down Expand Up @@ -883,7 +887,8 @@ public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
* @see #fromJson(String, Class)
* @since 2.10
*/
public <T> T fromJson(String json, TypeToken<T> typeOfT) throws JsonSyntaxException {
public <T> @Nullable T fromJson(@Nullable String json, TypeToken<T> typeOfT)
throws JsonSyntaxException {
if (json == null) {
return null;
}
Expand Down Expand Up @@ -914,7 +919,7 @@ public <T> T fromJson(String json, TypeToken<T> typeOfT) throws JsonSyntaxExcept
* @see #fromJson(String, Class)
* @see #fromJson(Reader, TypeToken)
*/
public <T> T fromJson(Reader json, Class<T> classOfT)
public <T> @Nullable T fromJson(Reader json, Class<T> classOfT)
throws JsonSyntaxException, JsonIOException {
return fromJson(json, TypeToken.get(classOfT));
}
Expand Down Expand Up @@ -945,7 +950,8 @@ public <T> T fromJson(Reader json, Class<T> classOfT)
* @see #fromJson(Reader, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
public <T> @Nullable T fromJson(Reader json, Type typeOfT)
throws JsonIOException, JsonSyntaxException {
return (T) fromJson(json, TypeToken.get(typeOfT));
}

Expand Down Expand Up @@ -975,7 +981,7 @@ public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyn
* @see #fromJson(Reader, Class)
* @since 2.10
*/
public <T> T fromJson(Reader json, TypeToken<T> typeOfT)
public <T> @Nullable T fromJson(Reader json, TypeToken<T> typeOfT)
throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = newJsonReader(json);
T object = fromJson(jsonReader, typeOfT);
Expand Down Expand Up @@ -1020,7 +1026,7 @@ public <T> T fromJson(Reader json, TypeToken<T> typeOfT)
* @see #fromJson(JsonReader, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
public <T> T fromJson(JsonReader reader, Type typeOfT)
public <T> @Nullable T fromJson(JsonReader reader, Type typeOfT)
throws JsonIOException, JsonSyntaxException {
return (T) fromJson(reader, TypeToken.get(typeOfT));
}
Expand Down Expand Up @@ -1061,7 +1067,7 @@ public <T> T fromJson(JsonReader reader, Type typeOfT)
* @see #fromJson(JsonReader, Type)
* @since 2.10
*/
public <T> T fromJson(JsonReader reader, TypeToken<T> typeOfT)
public <T> @Nullable T fromJson(JsonReader reader, TypeToken<T> typeOfT)
throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
Strictness oldStrictness = reader.getStrictness();
Expand Down Expand Up @@ -1133,7 +1139,8 @@ public <T> T fromJson(JsonReader reader, TypeToken<T> typeOfT)
* @see #fromJson(Reader, Class)
* @see #fromJson(JsonElement, TypeToken)
*/
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
public <T> @Nullable T fromJson(@Nullable JsonElement json, Class<T> classOfT)
throws JsonSyntaxException {
return fromJson(json, TypeToken.get(classOfT));
}

Expand All @@ -1160,7 +1167,8 @@ public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxExce
* @see #fromJson(JsonElement, TypeToken)
*/
@SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
public <T> @Nullable T fromJson(@Nullable JsonElement json, Type typeOfT)
throws JsonSyntaxException {
return (T) fromJson(json, TypeToken.get(typeOfT));
}

Expand All @@ -1186,14 +1194,15 @@ public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException
* @see #fromJson(JsonElement, Class)
* @since 2.10
*/
public <T> T fromJson(JsonElement json, TypeToken<T> typeOfT) throws JsonSyntaxException {
public <T> @Nullable T fromJson(@Nullable JsonElement json, TypeToken<T> 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.");
Expand All @@ -1214,7 +1223,7 @@ private static void assertFullConsumption(Object obj, JsonReader reader) {
* @see Gson#threadLocalAdapterResults
*/
static class FutureTypeAdapter<T> extends SerializationDelegatingTypeAdapter<T> {
private TypeAdapter<T> delegate = null;
private @Nullable TypeAdapter<T> delegate = null;

public void setDelegate(TypeAdapter<T> typeAdapter) {
if (delegate != null) {
Expand Down
11 changes: 6 additions & 5 deletions gson/src/main/java/com/google/gson/GsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -135,15 +136,15 @@ public final class GsonBuilder {
final List<TypeAdapterFactory> 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;
boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES;
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;
Expand Down Expand Up @@ -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);
Expand Down
13 changes: 7 additions & 6 deletions gson/src/main/java/com/google/gson/JsonArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
}

Expand All @@ -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));
}

Expand All @@ -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));
}

Expand All @@ -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));
}

Expand All @@ -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;
}
Expand All @@ -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);
}

Expand Down
Loading
Loading