aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcono1234 <Marcono1234@users.noreply.github.com>2022-09-09 16:32:55 +0200
committerGitHub <noreply@github.com>2022-09-09 07:32:55 -0700
commit847d7f66380e6bd54eedcdead2a95d4037ed87ee (patch)
tree373f2bd4f6428c0bd72ba5894756f42fe7db7c14
parent2266ccdd670b1e914c18aa5928ddd24c93deeed4 (diff)
downloadgson-847d7f66380e6bd54eedcdead2a95d4037ed87ee.tar.gz
Improve documentation (#2193)
* Improve JsonElement subclasses javadoc and add tests * Slightly improve JsonSerializer and JsonDeserializer javadoc * Improve ReflectionAccessTest failure message * Improve documentation regarding field and class exclusion
-rw-r--r--UserGuide.md3
-rw-r--r--gson/src/main/java/com/google/gson/ExclusionStrategy.java9
-rw-r--r--gson/src/main/java/com/google/gson/GsonBuilder.java43
-rw-r--r--gson/src/main/java/com/google/gson/JsonArray.java9
-rw-r--r--gson/src/main/java/com/google/gson/JsonDeserializer.java6
-rw-r--r--gson/src/main/java/com/google/gson/JsonNull.java15
-rw-r--r--gson/src/main/java/com/google/gson/JsonObject.java55
-rw-r--r--gson/src/main/java/com/google/gson/JsonPrimitive.java9
-rw-r--r--gson/src/main/java/com/google/gson/JsonSerializer.java4
-rw-r--r--gson/src/test/java/com/google/gson/JsonObjectTest.java18
-rw-r--r--gson/src/test/java/com/google/gson/functional/ReflectionAccessTest.java5
11 files changed, 133 insertions, 43 deletions
diff --git a/UserGuide.md b/UserGuide.md
index ec7fb7eb..12b53351 100644
--- a/UserGuide.md
+++ b/UserGuide.md
@@ -155,7 +155,8 @@ BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
* While serializing, a null field is omitted from the output.
* While deserializing, a missing entry in JSON results in setting the corresponding field in the object to its default value: null for object types, zero for numeric types, and false for booleans.
* If a field is _synthetic_, it is ignored and not included in JSON serialization or deserialization.
-* Fields corresponding to the outer classes in inner classes, anonymous classes, and local classes are ignored and not included in serialization or deserialization.
+* Fields corresponding to the outer classes in inner classes are ignored and not included in serialization or deserialization.
+* Anonymous and local classes are excluded. They will be serialized as JSON `null` and when deserialized their JSON value is ignored and `null` is returned. Convert the classes to `static` nested classes to enable serialization and deserialization for them.
### <a name="TOC-Nested-Classes-including-Inner-Classes-"></a>Nested Classes (including Inner Classes)
diff --git a/gson/src/main/java/com/google/gson/ExclusionStrategy.java b/gson/src/main/java/com/google/gson/ExclusionStrategy.java
index bc0dc74a..557eddb2 100644
--- a/gson/src/main/java/com/google/gson/ExclusionStrategy.java
+++ b/gson/src/main/java/com/google/gson/ExclusionStrategy.java
@@ -17,11 +17,8 @@
package com.google.gson;
/**
- * A strategy (or policy) definition that is used to decide whether or not a field or top-level
- * class should be serialized or deserialized as part of the JSON output/input. For serialization,
- * if the {@link #shouldSkipClass(Class)} method returns true then that class or field type
- * will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
- * returns true, then it will not be set as part of the Java object structure.
+ * A strategy (or policy) definition that is used to decide whether or not a field or
+ * class should be serialized or deserialized as part of the JSON output/input.
*
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
*
@@ -64,7 +61,7 @@ package com.google.gson;
*
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
* the {@code GsonBuilder} is required. The following is an example of how you can use the
- * {@code GsonBuilder} to configure Gson to use one of the above sample:
+ * {@code GsonBuilder} to configure Gson to use one of the above samples:
* <pre class="code">
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
* Gson gson = new GsonBuilder()
diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java
index e28da7c7..8332ccb3 100644
--- a/gson/src/main/java/com/google/gson/GsonBuilder.java
+++ b/gson/src/main/java/com/google/gson/GsonBuilder.java
@@ -156,8 +156,11 @@ public final class GsonBuilder {
/**
* Configures Gson to excludes all class fields that have the specified modifiers. By default,
- * Gson will exclude all fields marked transient or static. This method will override that
- * behavior.
+ * Gson will exclude all fields marked {@code transient} or {@code static}. This method will
+ * override that behavior.
+ *
+ * <p>This is a convenience method which behaves as if an {@link ExclusionStrategy} which
+ * excludes these fields was {@linkplain #setExclusionStrategies(ExclusionStrategy...) registered with this builder}.
*
* @param modifiers the field modifiers. You must use the modifiers specified in the
* {@link java.lang.reflect.Modifier} class. For example,
@@ -186,9 +189,12 @@ public final class GsonBuilder {
}
/**
- * Configures Gson to exclude all fields from consideration for serialization or deserialization
+ * Configures Gson to exclude all fields from consideration for serialization and deserialization
* that do not have the {@link com.google.gson.annotations.Expose} annotation.
*
+ * <p>This is a convenience method which behaves as if an {@link ExclusionStrategy} which excludes
+ * these fields was {@linkplain #setExclusionStrategies(ExclusionStrategy...) registered with this builder}.
+ *
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
@@ -291,7 +297,20 @@ public final class GsonBuilder {
}
/**
- * Configures Gson to exclude inner classes during serialization.
+ * Configures Gson to exclude inner classes (= non-{@code static} nested classes) during serialization
+ * and deserialization. This is a convenience method which behaves as if an {@link ExclusionStrategy}
+ * which excludes inner classes was {@linkplain #setExclusionStrategies(ExclusionStrategy...) registered with this builder}.
+ * This means inner classes will be serialized as JSON {@code null}, and will be deserialized as
+ * Java {@code null} with their JSON data being ignored. And fields with an inner class as type will
+ * be ignored during serialization and deserialization.
+ *
+ * <p>By default Gson serializes and deserializes inner classes, but ignores references to the
+ * enclosing instance. Deserialization might not be possible at all when {@link #disableJdkUnsafe()}
+ * is used (and no custom {@link InstanceCreator} is registered), or it can lead to unexpected
+ * {@code NullPointerException}s when the deserialized instance is used afterwards.
+ *
+ * <p>In general using inner classes with Gson should be avoided; they should be converted to {@code static}
+ * nested classes if possible.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
@@ -369,6 +388,16 @@ public final class GsonBuilder {
* The strategies are added to the existing strategies (if any); the existing strategies
* are not replaced.
*
+ * <p>Fields are excluded for serialization and deserialization when
+ * {@link ExclusionStrategy#shouldSkipField(FieldAttributes) shouldSkipField} returns {@code true},
+ * or when {@link ExclusionStrategy#shouldSkipClass(Class) shouldSkipClass} returns {@code true}
+ * for the field type. Gson behaves as if the field did not exist; its value is not serialized
+ * and on deserialization if a JSON member with this name exists it is skipped by default.<br>
+ * When objects of an excluded type (as determined by
+ * {@link ExclusionStrategy#shouldSkipClass(Class) shouldSkipClass}) are serialized a
+ * JSON null is written to output, and when deserialized the JSON value is skipped and
+ * {@code null} is returned.
+ *
* @param strategies the set of strategy object to apply during object (de)serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4
@@ -389,6 +418,9 @@ public final class GsonBuilder {
* class) should be skipped then that field (or object) is skipped during its
* serialization.
*
+ * <p>See the documentation of {@link #setExclusionStrategies(ExclusionStrategy...)}
+ * for a detailed description of the effect of exclusion strategies.
+ *
* @param strategy an exclusion strategy to apply during serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
@@ -407,6 +439,9 @@ public final class GsonBuilder {
* class) should be skipped then that field (or object) is skipped during its
* deserialization.
*
+ * <p>See the documentation of {@link #setExclusionStrategies(ExclusionStrategy...)}
+ * for a detailed description of the effect of exclusion strategies.
+ *
* @param strategy an exclusion strategy to apply during deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
diff --git a/gson/src/main/java/com/google/gson/JsonArray.java b/gson/src/main/java/com/google/gson/JsonArray.java
index cf5b77d3..d861cfb3 100644
--- a/gson/src/main/java/com/google/gson/JsonArray.java
+++ b/gson/src/main/java/com/google/gson/JsonArray.java
@@ -387,11 +387,20 @@ public final class JsonArray extends JsonElement implements Iterable<JsonElement
return getAsSingleElement().getAsBoolean();
}
+ /**
+ * Returns whether the other object is equal to this. This method only considers
+ * the other object to be equal if it is an instance of {@code JsonArray} and has
+ * equal elements in the same order.
+ */
@Override
public boolean equals(Object o) {
return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements));
}
+ /**
+ * Returns the hash code of this array. This method calculates the hash code based
+ * on the elements of this array.
+ */
@Override
public int hashCode() {
return elements.hashCode();
diff --git a/gson/src/main/java/com/google/gson/JsonDeserializer.java b/gson/src/main/java/com/google/gson/JsonDeserializer.java
index 0589eb28..46550edf 100644
--- a/gson/src/main/java/com/google/gson/JsonDeserializer.java
+++ b/gson/src/main/java/com/google/gson/JsonDeserializer.java
@@ -19,7 +19,7 @@ package com.google.gson;
import java.lang.reflect.Type;
/**
- * <p>Interface representing a custom deserializer for Json. You should write a custom
+ * <p>Interface representing a custom deserializer for JSON. You should write a custom
* deserializer, if you are not happy with the default deserialization done by Gson. You will
* also need to register this deserializer through
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}.</p>
@@ -42,9 +42,9 @@ import java.lang.reflect.Type;
* </pre>
*
* <p>The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
- * Json string to be <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you already know
+ * JSON string to be <code>{"clazz":"com.foo.MyObject","value":20}</code>. Suppose, you already know
* the type of the field that the {@code Id} will be deserialized into, and hence just want to
- * deserialize it from a Json string {@code 20}. You can achieve that by writing a custom
+ * deserialize it from a JSON string {@code 20}. You can achieve that by writing a custom
* deserializer:</p>
*
* <pre>
diff --git a/gson/src/main/java/com/google/gson/JsonNull.java b/gson/src/main/java/com/google/gson/JsonNull.java
index 934dfc7d..b14fd3f1 100644
--- a/gson/src/main/java/com/google/gson/JsonNull.java
+++ b/gson/src/main/java/com/google/gson/JsonNull.java
@@ -17,7 +17,7 @@
package com.google.gson;
/**
- * A class representing a Json {@code null} value.
+ * A class representing a JSON {@code null} value.
*
* @author Inderjeet Singh
* @author Joel Leitch
@@ -25,16 +25,16 @@ package com.google.gson;
*/
public final class JsonNull extends JsonElement {
/**
- * Singleton for JsonNull
+ * Singleton for {@code JsonNull}.
*
* @since 1.8
*/
public static final JsonNull INSTANCE = new JsonNull();
/**
- * Creates a new JsonNull object.
+ * Creates a new {@code JsonNull} object.
*
- * @deprecated Deprecated since Gson version 1.8. Use {@link #INSTANCE} instead
+ * @deprecated Deprecated since Gson version 1.8, use {@link #INSTANCE} instead.
*/
@Deprecated
public JsonNull() {
@@ -42,7 +42,8 @@ public final class JsonNull extends JsonElement {
}
/**
- * Returns the same instance since it is an immutable value
+ * Returns the same instance since it is an immutable value.
+ *
* @since 2.8.2
*/
@Override
@@ -51,7 +52,7 @@ public final class JsonNull extends JsonElement {
}
/**
- * All instances of JsonNull have the same hash code since they are indistinguishable
+ * All instances of {@code JsonNull} have the same hash code since they are indistinguishable.
*/
@Override
public int hashCode() {
@@ -59,7 +60,7 @@ public final class JsonNull extends JsonElement {
}
/**
- * All instances of JsonNull are the same
+ * All instances of {@code JsonNull} are considered equal.
*/
@Override
public boolean equals(Object other) {
diff --git a/gson/src/main/java/com/google/gson/JsonObject.java b/gson/src/main/java/com/google/gson/JsonObject.java
index 0c3a6885..4b600510 100644
--- a/gson/src/main/java/com/google/gson/JsonObject.java
+++ b/gson/src/main/java/com/google/gson/JsonObject.java
@@ -41,7 +41,8 @@ public final class JsonObject extends JsonElement {
}
/**
- * Creates a deep copy of this element and all its children
+ * Creates a deep copy of this element and all its children.
+ *
* @since 2.8.2
*/
@Override
@@ -55,7 +56,7 @@ public final class JsonObject extends JsonElement {
/**
* Adds a member, which is a name-value pair, to self. The name must be a String, but the value
- * can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
+ * can be an arbitrary {@link JsonElement}, thereby allowing you to build a full tree of JsonElements
* rooted at this node.
*
* @param property name of the member.
@@ -66,10 +67,11 @@ public final class JsonObject extends JsonElement {
}
/**
- * Removes the {@code property} from this {@link JsonObject}.
+ * Removes the {@code property} from this object.
*
* @param property name of the member that should be removed.
- * @return the {@link JsonElement} object that is being removed.
+ * @return the {@link JsonElement} object that is being removed, or {@code null} if no
+ * member with this name exists.
* @since 1.3
*/
public JsonElement remove(String property) {
@@ -77,8 +79,8 @@ public final class JsonObject extends JsonElement {
}
/**
- * Convenience method to add a primitive member. The specified value is converted to a
- * JsonPrimitive of String.
+ * Convenience method to add a string member. The specified value is converted to a
+ * {@link JsonPrimitive} of String.
*
* @param property name of the member.
* @param value the string value associated with the member.
@@ -88,8 +90,8 @@ public final class JsonObject extends JsonElement {
}
/**
- * Convenience method to add a primitive member. The specified value is converted to a
- * JsonPrimitive of Number.
+ * Convenience method to add a number member. The specified value is converted to a
+ * {@link JsonPrimitive} of Number.
*
* @param property name of the member.
* @param value the number value associated with the member.
@@ -100,10 +102,10 @@ public final class JsonObject extends JsonElement {
/**
* Convenience method to add a boolean member. The specified value is converted to a
- * JsonPrimitive of Boolean.
+ * {@link JsonPrimitive} of Boolean.
*
* @param property name of the member.
- * @param value the number value associated with the member.
+ * @param value the boolean value associated with the member.
*/
public void addProperty(String property, Boolean value) {
add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
@@ -111,10 +113,10 @@ public final class JsonObject extends JsonElement {
/**
* Convenience method to add a char member. The specified value is converted to a
- * JsonPrimitive of Character.
+ * {@link JsonPrimitive} of Character.
*
* @param property name of the member.
- * @param value the number value associated with the member.
+ * @param value the char value associated with the member.
*/
public void addProperty(String property, Character value) {
add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value));
@@ -163,48 +165,63 @@ public final class JsonObject extends JsonElement {
* Returns the member with the specified name.
*
* @param memberName name of the member that is being requested.
- * @return the member matching the name. Null if no such member exists.
+ * @return the member matching the name, or {@code null} if no such member exists.
*/
public JsonElement get(String memberName) {
return members.get(memberName);
}
/**
- * Convenience method to get the specified member as a JsonPrimitive element.
+ * Convenience method to get the specified member as a {@link JsonPrimitive}.
*
* @param memberName name of the member being requested.
- * @return the JsonPrimitive corresponding to the specified member.
+ * @return the {@code JsonPrimitive} corresponding to the specified member, or {@code null} if no
+ * member with this name exists.
+ * @throws ClassCastException if the member is not of type {@code JsonPrimitive}.
*/
public JsonPrimitive getAsJsonPrimitive(String memberName) {
return (JsonPrimitive) members.get(memberName);
}
/**
- * Convenience method to get the specified member as a JsonArray.
+ * Convenience method to get the specified member as a {@link JsonArray}.
*
* @param memberName name of the member being requested.
- * @return the JsonArray corresponding to the specified member.
+ * @return the {@code JsonArray} corresponding to the specified member, or {@code null} if no
+ * member with this name exists.
+ * @throws ClassCastException if the member is not of type {@code JsonArray}.
*/
public JsonArray getAsJsonArray(String memberName) {
return (JsonArray) members.get(memberName);
}
/**
- * Convenience method to get the specified member as a JsonObject.
+ * Convenience method to get the specified member as a {@link JsonObject}.
*
* @param memberName name of the member being requested.
- * @return the JsonObject corresponding to the specified member.
+ * @return the {@code JsonObject} corresponding to the specified member, or {@code null} if no
+ * member with this name exists.
+ * @throws ClassCastException if the member is not of type {@code JsonObject}.
*/
public JsonObject getAsJsonObject(String memberName) {
return (JsonObject) members.get(memberName);
}
+ /**
+ * Returns whether the other object is equal to this. This method only considers
+ * the other object to be equal if it is an instance of {@code JsonObject} and has
+ * equal members, ignoring order.
+ */
@Override
public boolean equals(Object o) {
return (o == this) || (o instanceof JsonObject
&& ((JsonObject) o).members.equals(members));
}
+ /**
+ * Returns the hash code of this object. This method calculates the hash code based
+ * on the members of this object, ignoring order.
+ */
@Override
public int hashCode() {
return members.hashCode();
diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java
index f69ffd5f..92a8df15 100644
--- a/gson/src/main/java/com/google/gson/JsonPrimitive.java
+++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java
@@ -78,6 +78,7 @@ public final class JsonPrimitive extends JsonElement {
/**
* Returns the same value as primitives are immutable.
+ *
* @since 2.8.2
*/
@Override
@@ -243,6 +244,9 @@ public final class JsonPrimitive extends JsonElement {
}
}
+ /**
+ * Returns the hash code of this object.
+ */
@Override
public int hashCode() {
if (value == null) {
@@ -260,6 +264,11 @@ public final class JsonPrimitive extends JsonElement {
return value.hashCode();
}
+ /**
+ * Returns whether the other object is equal to this. This method only considers
+ * the other object to be equal if it is an instance of {@code JsonPrimitive} and
+ * has an equal value.
+ */
@Override
public boolean equals(Object obj) {
if (this == obj) {
diff --git a/gson/src/main/java/com/google/gson/JsonSerializer.java b/gson/src/main/java/com/google/gson/JsonSerializer.java
index 19eaf17d..9b3e1ed5 100644
--- a/gson/src/main/java/com/google/gson/JsonSerializer.java
+++ b/gson/src/main/java/com/google/gson/JsonSerializer.java
@@ -19,7 +19,7 @@ package com.google.gson;
import java.lang.reflect.Type;
/**
- * Interface representing a custom serializer for Json. You should write a custom serializer, if
+ * Interface representing a custom serializer for JSON. You should write a custom serializer, if
* you are not happy with the default serialization done by Gson. You will also need to register
* this serializer through {@link com.google.gson.GsonBuilder#registerTypeAdapter(Type, Object)}.
*
@@ -43,7 +43,7 @@ import java.lang.reflect.Type;
* </pre>
*
* <p>The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be
- * <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you just want the output to be
+ * <code>{"clazz":"com.foo.MyObject","value":20}</code>. Suppose, you just want the output to be
* the value instead, which is {@code 20} in this case. You can achieve that by writing a custom
* serializer:</p>
*
diff --git a/gson/src/test/java/com/google/gson/JsonObjectTest.java b/gson/src/test/java/com/google/gson/JsonObjectTest.java
index 8ae573ab..d12d12d8 100644
--- a/gson/src/test/java/com/google/gson/JsonObjectTest.java
+++ b/gson/src/test/java/com/google/gson/JsonObjectTest.java
@@ -50,6 +50,8 @@ public class JsonObjectTest extends TestCase {
assertEquals(value, removedElement);
assertFalse(jsonObj.has(propertyName));
assertNull(jsonObj.get(propertyName));
+
+ assertNull(jsonObj.remove(propertyName));
}
public void testAddingNullPropertyValue() throws Exception {
@@ -170,6 +172,22 @@ public class JsonObjectTest extends TestCase {
assertFalse(b.equals(a));
}
+ public void testEqualsHashCodeIgnoringOrder() {
+ JsonObject a = new JsonObject();
+ JsonObject b = new JsonObject();
+
+ a.addProperty("1", true);
+ b.addProperty("2", false);
+
+ a.addProperty("2", false);
+ b.addProperty("1", true);
+
+ assertEquals(Arrays.asList("1", "2"), new ArrayList<>(a.keySet()));
+ assertEquals(Arrays.asList("2", "1"), new ArrayList<>(b.keySet()));
+
+ MoreAsserts.assertEqualsAndHashCode(a, b);
+ }
+
public void testSize() {
JsonObject o = new JsonObject();
assertEquals(0, o.size());
diff --git a/gson/src/test/java/com/google/gson/functional/ReflectionAccessTest.java b/gson/src/test/java/com/google/gson/functional/ReflectionAccessTest.java
index ece35124..7b7dc303 100644
--- a/gson/src/test/java/com/google/gson/functional/ReflectionAccessTest.java
+++ b/gson/src/test/java/com/google/gson/functional/ReflectionAccessTest.java
@@ -8,6 +8,7 @@ import static org.junit.Assert.fail;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
@@ -111,8 +112,10 @@ public class ReflectionAccessTest {
// But deserialization should fail
Class<?> internalClass = Collections.emptyList().getClass();
try {
- gson.fromJson("{}", internalClass);
+ gson.fromJson("[]", internalClass);
fail("Missing exception; test has to be run with `--illegal-access=deny`");
+ } catch (JsonSyntaxException e) {
+ fail("Unexpected exception; test has to be run with `--illegal-access=deny`");
} catch (JsonIOException expected) {
assertTrue(expected.getMessage().startsWith(
"Failed making constructor 'java.util.Collections$EmptyList#EmptyList()' accessible; "