diff --git a/src/com/massivecraft/massivecore/xlib/gson/Gson.java b/src/com/massivecraft/massivecore/xlib/gson/Gson.java
index e078826b..d95fae1a 100644
--- a/src/com/massivecraft/massivecore/xlib/gson/Gson.java
+++ b/src/com/massivecraft/massivecore/xlib/gson/Gson.java
@@ -16,6 +16,21 @@
package com.massivecraft.massivecore.xlib.gson;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import com.massivecraft.massivecore.xlib.gson.internal.ConstructorConstructor;
import com.massivecraft.massivecore.xlib.gson.internal.Excluder;
import com.massivecraft.massivecore.xlib.gson.internal.Primitives;
@@ -38,21 +53,6 @@ import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import com.massivecraft.massivecore.xlib.gson.stream.MalformedJsonException;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
/**
* This is the main class for using Gson. Gson is typically used by first constructing a
* Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)}
@@ -233,13 +233,13 @@ public final class Gson {
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
- factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor));
+ factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingPolicy, excluder));
@@ -411,7 +411,7 @@ public final class Gson {
* }
* Note that since you can not override type adapter factories for String and Java primitive
* types, our stats factory will not count the number of String or primitives that will be
- * read or written.
+ * read or written.
* @param skipPast The type adapter factory that needs to be skipped while searching for
* a matching type adapter. In most cases, you should just pass this (the type adapter
* factory from where {@link #getDelegateAdapter} method is being invoked).
@@ -421,6 +421,10 @@ public final class Gson {
*/
public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken type) {
boolean skipPastFound = false;
+ // Skip past if and only if the specified factory is present in the factories.
+ // This is useful because the factories created through JsonAdapter annotations are not
+ // registered in this list.
+ if (!factories.contains(skipPast)) skipPastFound = true;
for (TypeAdapterFactory factory : factories) {
if (!skipPastFound) {
diff --git a/src/com/massivecraft/massivecore/xlib/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java b/src/com/massivecraft/massivecore/xlib/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java
index 208d88d2..23b4af02 100644
--- a/src/com/massivecraft/massivecore/xlib/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java
+++ b/src/com/massivecraft/massivecore/xlib/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java
@@ -37,7 +37,7 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte
this.constructorConstructor = constructorConstructor;
}
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings("unchecked")
public TypeAdapter create(Gson gson, TypeToken targetType) {
JsonAdapter annotation = targetType.getRawType().getAnnotation(JsonAdapter.class);
if (annotation == null) {
diff --git a/src/com/massivecraft/massivecore/xlib/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/src/com/massivecraft/massivecore/xlib/gson/internal/bind/ReflectiveTypeAdapterFactory.java
index aff6be4d..30c87c0c 100644
--- a/src/com/massivecraft/massivecore/xlib/gson/internal/bind/ReflectiveTypeAdapterFactory.java
+++ b/src/com/massivecraft/massivecore/xlib/gson/internal/bind/ReflectiveTypeAdapterFactory.java
@@ -57,10 +57,18 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
}
public boolean excludeField(Field f, boolean serialize) {
+ return excludeField(f, serialize, excluder);
+ }
+
+ static boolean excludeField(Field f, boolean serialize, Excluder excluder) {
return !excluder.excludeClass(f.getType(), serialize) && !excluder.excludeField(f, serialize);
}
private String getFieldName(Field f) {
+ return getFieldName(fieldNamingPolicy, f);
+ }
+
+ static String getFieldName(FieldNamingStrategy fieldNamingPolicy, Field f) {
SerializedName serializedName = f.getAnnotation(SerializedName.class);
return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value();
}
@@ -98,6 +106,11 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
field.set(value, fieldValue);
}
}
+ public boolean writeField(Object value) throws IOException, IllegalAccessException {
+ if (!serialized) return false;
+ Object fieldValue = field.get(value);
+ return fieldValue != value; // avoid recursion for example for Throwable.cause
+ }
};
}
@@ -151,7 +164,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
this.serialized = serialized;
this.deserialized = deserialized;
}
-
+ abstract boolean writeField(Object value) throws IOException, IllegalAccessException;
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
}
@@ -202,7 +215,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
out.beginObject();
try {
for (BoundField boundField : boundFields.values()) {
- if (boundField.serialized) {
+ if (boundField.writeField(value)) {
out.name(boundField.name);
boundField.write(out, value);
}
diff --git a/src/com/massivecraft/massivecore/xlib/gson/internal/bind/TypeAdapters.java b/src/com/massivecraft/massivecore/xlib/gson/internal/bind/TypeAdapters.java
index 2398f258..a6de9755 100644
--- a/src/com/massivecraft/massivecore/xlib/gson/internal/bind/TypeAdapters.java
+++ b/src/com/massivecraft/massivecore/xlib/gson/internal/bind/TypeAdapters.java
@@ -746,23 +746,19 @@ public final class TypeAdapters {
}
}
- public static final TypeAdapterFactory ENUM_FACTORY = newEnumTypeHierarchyFactory();
-
- public static TypeAdapterFactory newEnumTypeHierarchyFactory() {
- return new TypeAdapterFactory() {
- @SuppressWarnings({"rawtypes", "unchecked"})
- public TypeAdapter create(Gson gson, TypeToken typeToken) {
- Class super T> rawType = typeToken.getRawType();
- if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
- return null;
- }
- if (!rawType.isEnum()) {
- rawType = rawType.getSuperclass(); // handle anonymous subclasses
- }
- return (TypeAdapter) new EnumTypeAdapter(rawType);
+ public static final TypeAdapterFactory ENUM_FACTORY = new TypeAdapterFactory() {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public TypeAdapter create(Gson gson, TypeToken typeToken) {
+ Class super T> rawType = typeToken.getRawType();
+ if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
+ return null;
}
- };
- }
+ if (!rawType.isEnum()) {
+ rawType = rawType.getSuperclass(); // handle anonymous subclasses
+ }
+ return (TypeAdapter) new EnumTypeAdapter(rawType);
+ }
+ };
public static TypeAdapterFactory newFactory(
final TypeToken type, final TypeAdapter typeAdapter) {
diff --git a/src/com/massivecraft/massivecore/xlib/gson/stream/JsonReader.java b/src/com/massivecraft/massivecore/xlib/gson/stream/JsonReader.java
index 7956807b..4d29ba19 100644
--- a/src/com/massivecraft/massivecore/xlib/gson/stream/JsonReader.java
+++ b/src/com/massivecraft/massivecore/xlib/gson/stream/JsonReader.java
@@ -364,6 +364,7 @@ public class JsonReader implements Closeable {
}
if (p == PEEKED_END_ARRAY) {
stackSize--;
+ pathIndices[stackSize - 1]++;
peeked = PEEKED_NONE;
} else {
throw new IllegalStateException("Expected END_ARRAY but was " + peek()
@@ -401,6 +402,7 @@ public class JsonReader implements Closeable {
if (p == PEEKED_END_OBJECT) {
stackSize--;
pathNames[stackSize] = null; // Free the last path name so that it can be garbage collected!
+ pathIndices[stackSize - 1]++;
peeked = PEEKED_NONE;
} else {
throw new IllegalStateException("Expected END_OBJECT but was " + peek()