Several breaking changes
This commit is contained in:
parent
ccf30b23e8
commit
dc4e61ac7b
|
@ -20,3 +20,4 @@ build
|
|||
.DS_Store
|
||||
|
||||
examples/android-proguard-example/gen
|
||||
.attach_pid*
|
14
README.md
14
README.md
|
@ -1,7 +1,17 @@
|
|||
# About this fork
|
||||
|
||||
This fork of Gson adds support for writing comments in JsonWriter.
|
||||
To do this, JsonWriter and CommentsTest were adjusted.
|
||||
This fork of Gson adds several features which were originally denied due to Gson's maintenance status.
|
||||
Among them are:
|
||||
- support for writing comments
|
||||
- collections with single entries without array syntax (`"single entry"` can become a `List` or array)
|
||||
- stricter leniency enforcement from the main Gson class (`toJson`, `fromJson` will respect the choice)
|
||||
- slightly better error messages
|
||||
- skipping empty entries in arrays (`["one",, "two",]`)
|
||||
- optionally omitting quotes around entry names like in Json5
|
||||
- support for hexadecimal integers
|
||||
|
||||
This means the only thing lacking for Json5 support is trailing commas in objects
|
||||
|
||||
Please be aware that I also increased the minimum java version to 11
|
||||
To use this, add the following:
|
||||
```groovy
|
||||
|
|
|
@ -35,12 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicLongArray;
|
||||
|
||||
import com.google.gson.internal.ConstructorConstructor;
|
||||
import com.google.gson.internal.Excluder;
|
||||
import com.google.gson.internal.GsonBuildConfig;
|
||||
import com.google.gson.internal.LazilyParsedNumber;
|
||||
import com.google.gson.internal.Primitives;
|
||||
import com.google.gson.internal.Streams;
|
||||
import com.google.gson.internal.*;
|
||||
import com.google.gson.internal.bind.ArrayTypeAdapter;
|
||||
import com.google.gson.internal.bind.CollectionTypeAdapterFactory;
|
||||
import com.google.gson.internal.bind.DateTypeAdapter;
|
||||
|
@ -104,23 +99,6 @@ import com.google.gson.stream.MalformedJsonException;
|
|||
* @author Jesse Wilson
|
||||
*/
|
||||
public final class Gson {
|
||||
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||
static final boolean DEFAULT_LENIENT = false;
|
||||
static final boolean DEFAULT_PRETTY_PRINT = false;
|
||||
static final boolean DEFAULT_ESCAPE_HTML = true;
|
||||
static final boolean DEFAULT_SERIALIZE_NULLS = false;
|
||||
static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
|
||||
static final boolean DEFAULT_DUPLICATE_MAP_KEYS = false;
|
||||
static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
|
||||
static final boolean DEFAULT_USE_JDK_UNSAFE = true;
|
||||
static final String DEFAULT_DATE_PATTERN = null;
|
||||
static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY = FieldNamingPolicy.IDENTITY;
|
||||
static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE;
|
||||
static final ToNumberStrategy DEFAULT_NUMBER_TO_NUMBER_STRATEGY = ToNumberPolicy.LAZILY_PARSED_NUMBER;
|
||||
|
||||
private static final TypeToken<?> NULL_KEY_SURROGATE = TypeToken.get(Object.class);
|
||||
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||
|
||||
/**
|
||||
* This thread local guards against reentrant calls to getAdapter(). In
|
||||
* certain object graphs, creating an adapter for a type may recursively
|
||||
|
@ -148,6 +126,7 @@ public final class Gson {
|
|||
final boolean htmlSafe;
|
||||
final boolean prettyPrinting;
|
||||
final boolean lenient;
|
||||
final boolean omitQuotes;
|
||||
final boolean serializeSpecialFloatingPointValues;
|
||||
final boolean useJdkUnsafe;
|
||||
final String datePattern;
|
||||
|
@ -195,21 +174,21 @@ public final class Gson {
|
|||
* </ul>
|
||||
*/
|
||||
public Gson() {
|
||||
this(Excluder.DEFAULT, DEFAULT_FIELD_NAMING_STRATEGY,
|
||||
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
|
||||
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_DUPLICATE_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
|
||||
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
|
||||
DEFAULT_USE_JDK_UNSAFE,
|
||||
LongSerializationPolicy.DEFAULT, DEFAULT_DATE_PATTERN, DateFormat.DEFAULT, DateFormat.DEFAULT,
|
||||
this(Excluder.DEFAULT, DefaultConfig.DEFAULT_FIELD_NAMING_STRATEGY,
|
||||
Collections.<Type, InstanceCreator<?>>emptyMap(), DefaultConfig.DEFAULT_SERIALIZE_NULLS,
|
||||
DefaultConfig.DEFAULT_COMPLEX_MAP_KEYS, DefaultConfig.DEFAULT_DUPLICATE_MAP_KEYS, DefaultConfig.DEFAULT_JSON_NON_EXECUTABLE, DefaultConfig.DEFAULT_ESCAPE_HTML,
|
||||
DefaultConfig.DEFAULT_PRETTY_PRINT, true, DefaultConfig.DEFAULT_OMIT_QUOTES, DefaultConfig.DEFAULT_SPECIALIZE_FLOAT_VALUES,
|
||||
DefaultConfig.DEFAULT_USE_JDK_UNSAFE,
|
||||
LongSerializationPolicy.DEFAULT, DefaultConfig.DEFAULT_DATE_PATTERN, DateFormat.DEFAULT, DateFormat.DEFAULT,
|
||||
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
|
||||
Collections.<TypeAdapterFactory>emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY,
|
||||
Collections.<TypeAdapterFactory>emptyList(), DefaultConfig.DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DefaultConfig.DEFAULT_NUMBER_TO_NUMBER_STRATEGY,
|
||||
Collections.<ReflectionAccessFilter>emptyList());
|
||||
}
|
||||
|
||||
Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
|
||||
Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
|
||||
boolean complexMapKeySerialization, boolean duplicateMapKeyDeserialization, boolean generateNonExecutableGson, boolean htmlSafe,
|
||||
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
|
||||
boolean prettyPrinting, boolean lenient, boolean omitQuotes, boolean serializeSpecialFloatingPointValues,
|
||||
boolean useJdkUnsafe,
|
||||
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
|
||||
int timeStyle, List<TypeAdapterFactory> builderFactories,
|
||||
|
@ -228,6 +207,7 @@ public final class Gson {
|
|||
this.htmlSafe = htmlSafe;
|
||||
this.prettyPrinting = prettyPrinting;
|
||||
this.lenient = lenient;
|
||||
this.omitQuotes = omitQuotes;
|
||||
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
|
||||
this.useJdkUnsafe = useJdkUnsafe;
|
||||
this.longSerializationPolicy = longSerializationPolicy;
|
||||
|
@ -481,7 +461,7 @@ public final class Gson {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
|
||||
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
|
||||
TypeAdapter<?> cached = typeTokenCache.get(type == null ? DefaultConfig.NULL_KEY_SURROGATE : type);
|
||||
if (cached != null) {
|
||||
return (TypeAdapter<T>) cached;
|
||||
}
|
||||
|
@ -745,7 +725,9 @@ public final class Gson {
|
|||
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
|
||||
TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
|
||||
boolean oldLenient = writer.isLenient();
|
||||
writer.setLenient(true);
|
||||
writer.setLenient(lenient);
|
||||
boolean oldOmitQuotes = writer.getOmitQuotes();
|
||||
writer.setOmitQuotes(omitQuotes);
|
||||
boolean oldHtmlSafe = writer.isHtmlSafe();
|
||||
writer.setHtmlSafe(htmlSafe);
|
||||
boolean oldSerializeNulls = writer.getSerializeNulls();
|
||||
|
@ -760,6 +742,7 @@ public final class Gson {
|
|||
throw error;
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setOmitQuotes(oldOmitQuotes);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
writer.setSerializeNulls(oldSerializeNulls);
|
||||
}
|
||||
|
@ -804,12 +787,13 @@ public final class Gson {
|
|||
* <li>{@link GsonBuilder#generateNonExecutableJson()}</li>
|
||||
* <li>{@link GsonBuilder#serializeNulls()}</li>
|
||||
* <li>{@link GsonBuilder#setLenient()}</li>
|
||||
* <li>{@link GsonBuilder#setOmitQuotes()}</li>
|
||||
* <li>{@link GsonBuilder#setPrettyPrinting()}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public JsonWriter newJsonWriter(Writer writer) throws IOException {
|
||||
if (generateNonExecutableJson) {
|
||||
writer.write(JSON_NON_EXECUTABLE_PREFIX);
|
||||
writer.write(DefaultConfig.JSON_NON_EXECUTABLE_PREFIX);
|
||||
}
|
||||
JsonWriter jsonWriter = new JsonWriter(writer);
|
||||
if (prettyPrinting) {
|
||||
|
@ -817,6 +801,7 @@ public final class Gson {
|
|||
}
|
||||
jsonWriter.setHtmlSafe(htmlSafe);
|
||||
jsonWriter.setLenient(lenient);
|
||||
jsonWriter.setOmitQuotes(omitQuotes);
|
||||
jsonWriter.setSerializeNulls(serializeNulls);
|
||||
return jsonWriter;
|
||||
}
|
||||
|
@ -841,7 +826,9 @@ public final class Gson {
|
|||
*/
|
||||
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
|
||||
boolean oldLenient = writer.isLenient();
|
||||
writer.setLenient(true);
|
||||
writer.setLenient(lenient);
|
||||
boolean oldOmitQuotes = writer.getOmitQuotes();
|
||||
writer.setOmitQuotes(omitQuotes);
|
||||
boolean oldHtmlSafe = writer.isHtmlSafe();
|
||||
writer.setHtmlSafe(htmlSafe);
|
||||
boolean oldSerializeNulls = writer.getSerializeNulls();
|
||||
|
@ -856,6 +843,7 @@ public final class Gson {
|
|||
throw error;
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setOmitQuotes(oldOmitQuotes);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
writer.setSerializeNulls(oldSerializeNulls);
|
||||
}
|
||||
|
@ -989,7 +977,7 @@ public final class Gson {
|
|||
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||
boolean isEmpty = true;
|
||||
boolean oldLenient = reader.isLenient();
|
||||
reader.setLenient(true);
|
||||
reader.setLenient(lenient);
|
||||
try {
|
||||
reader.peek();
|
||||
isEmpty = false;
|
||||
|
|
|
@ -35,18 +35,7 @@ import com.google.gson.internal.sql.SqlTypesSupport;
|
|||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
||||
import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
|
||||
import static com.google.gson.Gson.DEFAULT_DATE_PATTERN;
|
||||
import static com.google.gson.Gson.DEFAULT_DUPLICATE_MAP_KEYS;
|
||||
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
|
||||
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
|
||||
import static com.google.gson.Gson.DEFAULT_LENIENT;
|
||||
import static com.google.gson.Gson.DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
|
||||
import static com.google.gson.Gson.DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
|
||||
import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT;
|
||||
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
|
||||
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
|
||||
import static com.google.gson.Gson.DEFAULT_USE_JDK_UNSAFE;
|
||||
import static com.google.gson.internal.DefaultConfig.*;
|
||||
|
||||
/**
|
||||
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
|
||||
|
@ -100,6 +89,7 @@ public final class GsonBuilder {
|
|||
private boolean prettyPrinting = DEFAULT_PRETTY_PRINT;
|
||||
private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
|
||||
private boolean lenient = DEFAULT_LENIENT;
|
||||
private boolean omitQuotes = DEFAULT_OMIT_QUOTES;
|
||||
private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
|
||||
private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
|
||||
private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
|
||||
|
@ -131,6 +121,7 @@ public final class GsonBuilder {
|
|||
this.escapeHtmlChars = gson.htmlSafe;
|
||||
this.prettyPrinting = gson.prettyPrinting;
|
||||
this.lenient = gson.lenient;
|
||||
this.omitQuotes = gson.omitQuotes;
|
||||
this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues;
|
||||
this.longSerializationPolicy = gson.longSerializationPolicy;
|
||||
this.datePattern = gson.datePattern;
|
||||
|
@ -456,6 +447,15 @@ public final class GsonBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, Gson always writes quotes around entry names.
|
||||
* This option allows omitting quotes if the name is alphanumeric.
|
||||
*/
|
||||
public GsonBuilder setOmitQuotes() {
|
||||
omitQuotes = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, Gson escapes HTML characters such as < > etc. Use this option to configure
|
||||
* Gson to pass-through HTML characters as is.
|
||||
|
@ -694,7 +694,7 @@ public final class GsonBuilder {
|
|||
|
||||
return new Gson(excluder, fieldNamingPolicy, new HashMap<>(instanceCreators),
|
||||
serializeNulls, complexMapKeySerialization, duplicateMapKeyDeserialization,
|
||||
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
|
||||
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient, omitQuotes,
|
||||
serializeSpecialFloatingPointValues, useJdkUnsafe, longSerializationPolicy,
|
||||
datePattern, dateStyle, timeStyle, new ArrayList<>(this.factories),
|
||||
new ArrayList<>(this.hierarchyFactories), factories,
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.google.gson.internal;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.*;
|
||||
|
||||
public class DefaultConfig {
|
||||
public static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||
public static final boolean DEFAULT_LENIENT = false;
|
||||
public static final boolean DEFAULT_OMIT_QUOTES = false;
|
||||
public static final boolean DEFAULT_PRETTY_PRINT = false;
|
||||
public static final boolean DEFAULT_ESCAPE_HTML = true;
|
||||
public static final boolean DEFAULT_SERIALIZE_NULLS = false;
|
||||
public static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
|
||||
public static final boolean DEFAULT_DUPLICATE_MAP_KEYS = false;
|
||||
public static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
|
||||
public static final boolean DEFAULT_USE_JDK_UNSAFE = true;
|
||||
public static final String DEFAULT_DATE_PATTERN = null;
|
||||
public static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY = FieldNamingPolicy.IDENTITY;
|
||||
public static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE;
|
||||
public static final ToNumberStrategy DEFAULT_NUMBER_TO_NUMBER_STRATEGY = ToNumberPolicy.LAZILY_PARSED_NUMBER;
|
||||
public static final TypeToken<?> NULL_KEY_SURROGATE = TypeToken.get(Object.class);
|
||||
public static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||
}
|
|
@ -65,6 +65,13 @@ public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
|
|||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
Object array;
|
||||
if (in.isLenient() && in.peek() != JsonToken.BEGIN_ARRAY) {
|
||||
// Coerce
|
||||
array = Array.newInstance(componentType, 1);
|
||||
Array.set(array, 0, componentTypeAdapter.read(in));
|
||||
return array;
|
||||
}
|
||||
|
||||
List<E> list = new ArrayList<>();
|
||||
in.beginArray();
|
||||
|
@ -75,7 +82,7 @@ public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
|
|||
in.endArray();
|
||||
|
||||
int size = list.size();
|
||||
Object array = Array.newInstance(componentType, size);
|
||||
array = Array.newInstance(componentType, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
Array.set(array, i, list.get(i));
|
||||
}
|
||||
|
|
|
@ -77,12 +77,17 @@ public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
|
|||
}
|
||||
|
||||
Collection<E> collection = constructor.construct();
|
||||
in.beginArray();
|
||||
while (in.hasNext()) {
|
||||
E instance = elementTypeAdapter.read(in);
|
||||
collection.add(instance);
|
||||
if (!in.isLenient() || in.peek() == JsonToken.BEGIN_ARRAY) {
|
||||
in.beginArray();
|
||||
while (in.hasNext()) {
|
||||
E instance = elementTypeAdapter.read(in);
|
||||
collection.add(instance);
|
||||
}
|
||||
in.endArray();
|
||||
} else {
|
||||
// Coerce
|
||||
collection.add(elementTypeAdapter.read(in));
|
||||
}
|
||||
in.endArray();
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.google.gson.stream;
|
||||
|
||||
import com.google.gson.internal.JsonReaderInternalAccess;
|
||||
import com.google.gson.internal.*;
|
||||
import com.google.gson.internal.bind.JsonTreeReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
|
@ -226,7 +226,7 @@ public class JsonReader implements Closeable {
|
|||
private final Reader in;
|
||||
|
||||
/** True to accept non-spec compliant JSON */
|
||||
private boolean lenient = false;
|
||||
private boolean lenient = DefaultConfig.DEFAULT_LENIENT;
|
||||
|
||||
static final int BUFFER_SIZE = 1024;
|
||||
/**
|
||||
|
@ -315,8 +315,7 @@ public class JsonReader implements Closeable {
|
|||
* <li>Names that are unquoted or {@code 'single quoted'}.
|
||||
* <li>Strings that are unquoted or {@code 'single quoted'}.
|
||||
* <li>Array elements separated by {@code ;} instead of {@code ,}.
|
||||
* <li>Unnecessary array separators. These are interpreted as if null
|
||||
* was the omitted value.
|
||||
* <li>Unnecessary array separators. These are ignored.
|
||||
* <li>Names and values separated by {@code =} or {@code =>} instead of
|
||||
* {@code :}.
|
||||
* <li>Name/value pairs separated by {@code ;} instead of {@code ,}.
|
||||
|
@ -473,7 +472,7 @@ public class JsonReader implements Closeable {
|
|||
case ',':
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Unterminated array");
|
||||
throw syntaxError("Unterminated array at " + (char)c);
|
||||
}
|
||||
} else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) {
|
||||
stack[stackSize - 1] = JsonScope.DANGLING_NAME;
|
||||
|
@ -488,7 +487,7 @@ public class JsonReader implements Closeable {
|
|||
case ',':
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Unterminated object");
|
||||
throw syntaxError("Unterminated object at " + (char)c);
|
||||
}
|
||||
}
|
||||
int c = nextNonWhitespace(true);
|
||||
|
@ -546,35 +545,8 @@ public class JsonReader implements Closeable {
|
|||
throw new IllegalStateException("JsonReader is closed");
|
||||
}
|
||||
|
||||
int c = nextNonWhitespace(true);
|
||||
switch (c) {
|
||||
case ']':
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY) {
|
||||
return peeked = PEEKED_END_ARRAY;
|
||||
}
|
||||
// fall-through to handle ",]"
|
||||
case ';':
|
||||
case ',':
|
||||
// In lenient mode, a 0-length literal in an array means 'null'.
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
|
||||
checkLenient();
|
||||
pos--;
|
||||
return peeked = PEEKED_NULL;
|
||||
} else {
|
||||
throw syntaxError("Unexpected value");
|
||||
}
|
||||
case '\'':
|
||||
checkLenient();
|
||||
return peeked = PEEKED_SINGLE_QUOTED;
|
||||
case '"':
|
||||
return peeked = PEEKED_DOUBLE_QUOTED;
|
||||
case '[':
|
||||
return peeked = PEEKED_BEGIN_ARRAY;
|
||||
case '{':
|
||||
return peeked = PEEKED_BEGIN_OBJECT;
|
||||
default:
|
||||
pos--; // Don't consume the first character in a literal value.
|
||||
}
|
||||
if (checkNextNonWhitespace(peekStack))
|
||||
return peeked;
|
||||
|
||||
int result = peekKeyword();
|
||||
if (result != PEEKED_NONE) {
|
||||
|
@ -594,6 +566,45 @@ public class JsonReader implements Closeable {
|
|||
return peeked = PEEKED_UNQUOTED;
|
||||
}
|
||||
|
||||
private boolean checkNextNonWhitespace(int peekStack) throws IOException {
|
||||
int c = nextNonWhitespace(true);
|
||||
switch (c) {
|
||||
case ']':
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
|
||||
peeked = PEEKED_END_ARRAY;
|
||||
return true;
|
||||
}
|
||||
throw syntaxError("Unexpected value");
|
||||
case ';':
|
||||
case ',':
|
||||
// In lenient mode, a 0-length literal in an array should be skipped.
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
|
||||
checkLenient();
|
||||
//pos--;
|
||||
//peeked = PEEKED_NULL;
|
||||
return checkNextNonWhitespace(peekStack);
|
||||
} else {
|
||||
throw syntaxError("Unexpected value");
|
||||
}
|
||||
case '\'':
|
||||
checkLenient();
|
||||
peeked = PEEKED_SINGLE_QUOTED;
|
||||
return true;
|
||||
case '"':
|
||||
peeked = PEEKED_DOUBLE_QUOTED;
|
||||
return true;
|
||||
case '[':
|
||||
peeked = PEEKED_BEGIN_ARRAY;
|
||||
return true;
|
||||
case '{':
|
||||
peeked = PEEKED_BEGIN_OBJECT;
|
||||
return true;
|
||||
default:
|
||||
pos--; // Don't consume the first character in a literal value.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int peekKeyword() throws IOException {
|
||||
// Figure out which keyword we're matching against by its first character.
|
||||
char c = buffer[pos];
|
||||
|
@ -1198,10 +1209,14 @@ public class JsonReader implements Closeable {
|
|||
}
|
||||
|
||||
peeked = PEEKED_BUFFERED;
|
||||
double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
|
||||
result = (int) asDouble;
|
||||
if (result != asDouble) { // Make sure no precision was lost casting to 'int'.
|
||||
throw new NumberFormatException("Expected an int but was " + peekedString + locationString());
|
||||
if (peekedString.startsWith("0x")) {
|
||||
result = Integer.decode(peekedString);
|
||||
} else {
|
||||
double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
|
||||
result = (int) asDouble;
|
||||
if (result != asDouble) { // Make sure no precision was lost casting to 'int'.
|
||||
throw new NumberFormatException("Expected an int but was " + peekedString + locationString());
|
||||
}
|
||||
}
|
||||
peekedString = null;
|
||||
peeked = PEEKED_NONE;
|
||||
|
@ -1254,7 +1269,8 @@ public class JsonReader implements Closeable {
|
|||
pos += peekedNumberLength;
|
||||
}
|
||||
peeked = PEEKED_NONE;
|
||||
} while (count != 0);
|
||||
} while (count > 0);
|
||||
if (count < 0) throw new IllegalStateException("Attempt to skip led outside its parent");
|
||||
|
||||
pathIndices[stackSize - 1]++;
|
||||
pathNames[stackSize - 1] = "null";
|
||||
|
@ -1452,7 +1468,8 @@ public class JsonReader implements Closeable {
|
|||
String locationString() {
|
||||
int line = lineNumber + 1;
|
||||
int column = pos - lineStart + 1;
|
||||
return " at line " + line + " column " + column + " path " + getPath();
|
||||
String charInterjection = pos < buffer.length ? " (char '" + buffer[pos] + "')" : "";
|
||||
return " at line " + line + " column " + column + charInterjection + " path " + getPath();
|
||||
}
|
||||
|
||||
private String getPath(boolean usePreviousPath) {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.google.gson.stream;
|
||||
|
||||
import com.google.gson.internal.*;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
|
@ -190,7 +192,9 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
*/
|
||||
private String separator = ":";
|
||||
|
||||
private boolean lenient;
|
||||
private boolean lenient = DefaultConfig.DEFAULT_LENIENT;
|
||||
|
||||
private boolean omitQuotes = DefaultConfig.DEFAULT_OMIT_QUOTES;
|
||||
|
||||
private boolean htmlSafe;
|
||||
|
||||
|
@ -286,11 +290,25 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
return serializeNulls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether serialized entry names may omit quotes (like in json5)
|
||||
* The default is false
|
||||
*/
|
||||
public final void setOmitQuotes(boolean omitQuotes) {
|
||||
this.omitQuotes = omitQuotes;
|
||||
}
|
||||
|
||||
public final boolean getOmitQuotes() {
|
||||
return omitQuotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a comment at the current location.
|
||||
* May create a new line.
|
||||
* This writer MUST be lenient to use this
|
||||
*/
|
||||
public JsonWriter comment(String comment) throws IOException {
|
||||
if (!lenient) throw new MalformedJsonException("Cannot write comment in non-lenient JsonWriter.");
|
||||
if (comment == null || comment.isBlank()) return this;
|
||||
String[] parts = comment.split("\n");
|
||||
if (indent == null) {
|
||||
|
@ -424,7 +442,12 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
private void writeDeferredName() throws IOException {
|
||||
if (deferredName != null) {
|
||||
beforeName();
|
||||
string(deferredName);
|
||||
if (omitQuotes && deferredName.matches("[a-zA-Z_$][\\w$]*")) {
|
||||
out.write(deferredName);
|
||||
}
|
||||
else {
|
||||
string(deferredName);
|
||||
}
|
||||
deferredName = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public final class GsonTest extends TestCase {
|
|||
public void testOverridesDefaultExcluder() {
|
||||
Gson gson = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
|
||||
new HashMap<Type, InstanceCreator<?>>(), true, false, false, true, false,
|
||||
true, true, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
true, true, false, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
|
||||
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>(),
|
||||
CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY,
|
||||
|
@ -69,7 +69,7 @@ public final class GsonTest extends TestCase {
|
|||
public void testClonedTypeAdapterFactoryListsAreIndependent() {
|
||||
Gson original = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
|
||||
new HashMap<Type, InstanceCreator<?>>(), true, false, false, true, false,
|
||||
true, true, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
true, true, false, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
|
||||
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>(),
|
||||
CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY,
|
||||
|
@ -91,7 +91,7 @@ public final class GsonTest extends TestCase {
|
|||
|
||||
public void testNewJsonWriter_Default() throws IOException {
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonWriter jsonWriter = new Gson().newJsonWriter(writer);
|
||||
JsonWriter jsonWriter = new GsonBuilder().create().newJsonWriter(writer);
|
||||
jsonWriter.beginObject();
|
||||
jsonWriter.name("test");
|
||||
jsonWriter.nullValue();
|
||||
|
@ -137,7 +137,7 @@ public final class GsonTest extends TestCase {
|
|||
|
||||
public void testNewJsonReader_Default() throws IOException {
|
||||
String json = "test"; // String without quotes
|
||||
JsonReader jsonReader = new Gson().newJsonReader(new StringReader(json));
|
||||
JsonReader jsonReader = new GsonBuilder().create().newJsonReader(new StringReader(json));
|
||||
try {
|
||||
jsonReader.nextString();
|
||||
fail();
|
||||
|
|
|
@ -203,7 +203,7 @@ public final class MixedStreamTest extends TestCase {
|
|||
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(writer);
|
||||
new GsonBuilder().serializeSpecialFloatingPointValues().create()
|
||||
new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create()
|
||||
.toJson(doubles, type, jsonWriter);
|
||||
assertEquals("[NaN,-Infinity,Infinity,-0.0,0.5,0.0]", writer.toString());
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class ToNumberPolicyTest extends TestCase {
|
|||
strategy.readNumber(fromString("1e400"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("JSON forbids NaN and infinities: Infinity at line 1 column 6 path $", expected.getMessage());
|
||||
assertEquals("JSON forbids NaN and infinities: Infinity at line 1 column 6 (char '\0') path $", expected.getMessage());
|
||||
}
|
||||
try {
|
||||
strategy.readNumber(fromString("\"not-a-number\""));
|
||||
|
@ -74,19 +74,19 @@ public class ToNumberPolicyTest extends TestCase {
|
|||
strategy.readNumber(fromString("NaN"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $", expected.getMessage());
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 (char 'N') path $", expected.getMessage());
|
||||
}
|
||||
try {
|
||||
strategy.readNumber(fromString("Infinity"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $", expected.getMessage());
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 (char 'I') path $", expected.getMessage());
|
||||
}
|
||||
try {
|
||||
strategy.readNumber(fromString("-Infinity"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $", expected.getMessage());
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 (char '-') path $", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ public class ArrayTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testArrayOfPrimitivesAsObjectsDeserialization() throws Exception {
|
||||
String json = "[1,'abc',0.3,1.1,5]";
|
||||
String json = "[1,\"abc\",0.3,1.1,5]";
|
||||
Object[] objs = gson.fromJson(json, Object[].class);
|
||||
assertEquals(1, ((Number)objs[0]).intValue());
|
||||
assertEquals("abc", objs[1]);
|
||||
|
@ -249,8 +249,8 @@ public class ArrayTest extends TestCase {
|
|||
* Regression tests for Issue 272
|
||||
*/
|
||||
public void testMultidimenstionalArraysDeserialization() {
|
||||
String json = "[['3m Co','71.72','0.02','0.03','4/2 12:00am','Manufacturing'],"
|
||||
+ "['Alcoa Inc','29.01','0.42','1.47','4/1 12:00am','Manufacturing']]";
|
||||
String json = "[[\"3m Co\",\"71.72\",\"0.02\",\"0.03\",\"4/2 12:00am\",\"Manufacturing\"],"
|
||||
+ "[\"Alcoa Inc\",\"29.01\",\"0.42\",\"1.47\",\"4/1 12:00am\",\"Manufacturing\"]]";
|
||||
String[][] items = gson.fromJson(json, String[][].class);
|
||||
assertEquals("3m Co", items[0][0]);
|
||||
assertEquals("Manufacturing", items[1][5]);
|
||||
|
|
|
@ -101,7 +101,7 @@ public class CollectionTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testLinkedListDeserialization() {
|
||||
String json = "['a1','a2']";
|
||||
String json = "[\"a1\",\"a2\"]";
|
||||
Type linkedListType = new TypeToken<LinkedList<String>>() {}.getType();
|
||||
List<String> list = gson.fromJson(json, linkedListType);
|
||||
assertEquals("a1", list.get(0));
|
||||
|
@ -119,7 +119,7 @@ public class CollectionTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testQueueDeserialization() {
|
||||
String json = "['a1','a2']";
|
||||
String json = "[\"a1\",\"a2\"]";
|
||||
Type queueType = new TypeToken<Queue<String>>() {}.getType();
|
||||
Queue<String> queue = gson.fromJson(json, queueType);
|
||||
assertEquals("a1", queue.element());
|
||||
|
@ -385,7 +385,7 @@ public class CollectionTest extends TestCase {
|
|||
assertTrue(json.contains("2"));
|
||||
}
|
||||
public void testSetDeserialization() {
|
||||
String json = "[{value:1},{value:2}]";
|
||||
String json = "[{\"value\":1},{\"value\":2}]";
|
||||
Type type = new TypeToken<Set<Entry>>() {}.getType();
|
||||
Set<Entry> set = gson.fromJson(json, type);
|
||||
assertEquals(2, set.size());
|
||||
|
|
|
@ -56,7 +56,7 @@ public class ConcurrencyTest extends TestCase {
|
|||
*/
|
||||
public void testSingleThreadDeserialization() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
gson.fromJson("{'a':'hello','b':'world','i':1}", MyObject.class);
|
||||
gson.fromJson("{\"a\":\"hello\",\"b\":\"world\",\"i\":1}", MyObject.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class ConcurrencyTest extends TestCase {
|
|||
try {
|
||||
startLatch.await();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
gson.fromJson("{'a':'hello','b':'world','i':1}", MyObject.class);
|
||||
gson.fromJson("{\"a\":\"hello\",\"b\":\"world\",\"i\":1}", MyObject.class);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed.set(true);
|
||||
|
|
|
@ -112,12 +112,11 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testJsonTypeFieldBasedDeserialization() {
|
||||
String json = "{field1:'abc',field2:'def',__type__:'SUB_TYPE1'}";
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(MyBase.class, new JsonDeserializer<MyBase>() {
|
||||
@Override public MyBase deserialize(JsonElement json, Type pojoType,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
String type = json.getAsJsonObject().get(MyBase.TYPE_ACCESS).getAsString();
|
||||
return context.deserialize(json, SubTypes.valueOf(type).getSubclass());
|
||||
}
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(MyBase.class, (JsonDeserializer<MyBase>) (json1, pojoType, context) -> {
|
||||
String type = json1.getAsJsonObject().get(MyBase.TYPE_ACCESS).getAsString();
|
||||
return context.deserialize(json1, SubTypes.valueOf(type).getSubclass());
|
||||
}).create();
|
||||
SubType1 target = (SubType1) gson.fromJson(json, MyBase.class);
|
||||
assertEquals("abc", target.field1);
|
||||
|
@ -150,13 +149,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNullForTopLevelObject() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "{baseName:'Base',subName:'SubRevised'}";
|
||||
Base target = gson.fromJson(json, Base.class);
|
||||
assertNull(target);
|
||||
|
@ -164,13 +158,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNull() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
|
||||
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
|
||||
assertNull(target.base);
|
||||
|
@ -178,13 +167,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNullForArrayElements() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "[{baseName:'Base'},{baseName:'Base'}]";
|
||||
Base[] target = gson.fromJson(json, Base[].class);
|
||||
assertNull(target[0]);
|
||||
|
@ -193,13 +177,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNullForArrayElementsForArrayField() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "{bases:[{baseName:'Base'},{baseName:'Base'}]}";
|
||||
ClassWithBaseArray target = gson.fromJson(json, ClassWithBaseArray.class);
|
||||
assertNull(target.bases[0]);
|
||||
|
|
|
@ -264,7 +264,7 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
}
|
||||
});
|
||||
Gson gson = gsonBuilder.create();
|
||||
String json = "'0123456789'";
|
||||
String json = "\"0123456789\"";
|
||||
byte[] actual = gson.fromJson(json, byte[].class);
|
||||
byte[] expected = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
for (int i = 0; i < actual.length; ++i) {
|
||||
|
@ -338,7 +338,7 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
.registerTypeAdapter(StringHolder.class, new StringHolderTypeAdapter())
|
||||
.create();
|
||||
Type setType = new TypeToken<Set<StringHolder>>() {}.getType();
|
||||
Set<StringHolder> setOfHolders = gson.fromJson("['Jacob:Tomaw']", setType);
|
||||
Set<StringHolder> setOfHolders = gson.fromJson("[\"Jacob:Tomaw\"]", setType);
|
||||
assertEquals(1, setOfHolders.size());
|
||||
StringHolder foo = setOfHolders.iterator().next();
|
||||
assertEquals("Jacob", foo.part1);
|
||||
|
@ -376,7 +376,7 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
.registerTypeAdapter(StringHolder.class, new StringHolderTypeAdapter())
|
||||
.create();
|
||||
Type mapType = new TypeToken<Map<String, StringHolder>>() {}.getType();
|
||||
Map<String, StringHolder> mapOfFoo = gson.fromJson("{'foo':'Jacob:Tomaw'}", mapType);
|
||||
Map<String, StringHolder> mapOfFoo = gson.fromJson("{\"foo\":\"Jacob:Tomaw\"}", mapType);
|
||||
assertEquals(1, mapOfFoo.size());
|
||||
StringHolder foo = mapOfFoo.get("foo");
|
||||
assertEquals("Jacob", foo.part1);
|
||||
|
@ -394,8 +394,9 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
|
||||
public void testEnsureCustomDeserializerNotInvokedForNullValues() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(DataHolder.class, new DataHolderDeserializer())
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(DataHolder.class, new DataHolderDeserializer())
|
||||
.create();
|
||||
String json = "{wrappedData:null}";
|
||||
DataHolderWrapper actual = gson.fromJson(json, DataHolderWrapper.class);
|
||||
assertNull(actual.wrappedData);
|
||||
|
@ -404,8 +405,8 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
// Test created from Issue 352
|
||||
public void testRegisterHierarchyAdapterForDate() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeHierarchyAdapter(Date.class, new DateTypeAdapter())
|
||||
.create();
|
||||
.registerTypeHierarchyAdapter(Date.class, new DateTypeAdapter())
|
||||
.create();
|
||||
assertEquals("0", gson.toJson(new Date(0)));
|
||||
assertEquals("0", gson.toJson(new java.sql.Date(0)));
|
||||
assertEquals(new Date(0), gson.fromJson("0", Date.class));
|
||||
|
|
|
@ -104,7 +104,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
// Override with a custom type adapter for class.
|
||||
gson = new GsonBuilder().registerTypeAdapter(Class.class, new MyClassTypeAdapter()).create();
|
||||
gson = new GsonBuilder().setLenient().registerTypeAdapter(Class.class, new MyClassTypeAdapter()).create();
|
||||
assertEquals(String.class, gson.fromJson("java.lang.String", Class.class));
|
||||
}
|
||||
|
||||
|
@ -410,7 +410,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultCalendarDeserialization() throws Exception {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
Gson gson = new Gson();
|
||||
String json = "{year:2009,month:2,dayOfMonth:11,hourOfDay:14,minute:29,second:23}";
|
||||
Calendar cal = gson.fromJson(json, Calendar.class);
|
||||
assertEquals(2009, cal.get(Calendar.YEAR));
|
||||
|
@ -434,7 +434,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultGregorianCalendarDeserialization() throws Exception {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
Gson gson = new Gson();
|
||||
String json = "{year:2009,month:2,dayOfMonth:11,hourOfDay:14,minute:29,second:23}";
|
||||
GregorianCalendar cal = gson.fromJson(json, GregorianCalendar.class);
|
||||
assertEquals(2009, cal.get(Calendar.YEAR));
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Functional tests for enums with Proguard.
|
||||
*
|
||||
* @author Young Cha
|
||||
*/
|
||||
public class EnumWithObfuscatedTest extends TestCase {
|
||||
private Gson gson;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
public enum Gender {
|
||||
@SerializedName("MAIL")
|
||||
MALE,
|
||||
|
||||
@SerializedName("FEMAIL")
|
||||
FEMALE
|
||||
}
|
||||
|
||||
public void testEnumClassWithObfuscated() {
|
||||
for (Gender enumConstant: Gender.class.getEnumConstants()) {
|
||||
try {
|
||||
Gender.class.getField(enumConstant.name());
|
||||
fail("Enum is not obfuscated");
|
||||
} catch (NoSuchFieldException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(Gender.MALE, gson.fromJson("\"MAIL\"", Gender.class));
|
||||
assertEquals("\"MAIL\"", gson.toJson(Gender.MALE, Gender.class));
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ public class ExposeFieldsTest extends TestCase {
|
|||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.excludeFieldsWithoutExposeAnnotation()
|
||||
.registerTypeAdapter(SomeInterface.class, new SomeInterfaceInstanceCreator())
|
||||
.create();
|
||||
|
|
|
@ -42,12 +42,9 @@ public class InstanceCreatorTest extends TestCase {
|
|||
|
||||
public void testInstanceCreatorReturnsBaseType() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new InstanceCreator<Base>() {
|
||||
@Override public Base createInstance(Type type) {
|
||||
return new Base();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (InstanceCreator<Base>) type -> new Base())
|
||||
.create();
|
||||
String json = "{baseName:'BaseRevised',subName:'Sub'}";
|
||||
Base base = gson.fromJson(json, Base.class);
|
||||
assertEquals("BaseRevised", base.baseName);
|
||||
|
@ -55,12 +52,9 @@ public class InstanceCreatorTest extends TestCase {
|
|||
|
||||
public void testInstanceCreatorReturnsSubTypeForTopLevelObject() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new InstanceCreator<Base>() {
|
||||
@Override public Base createInstance(Type type) {
|
||||
return new Sub();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (InstanceCreator<Base>) type -> new Sub())
|
||||
.create();
|
||||
|
||||
String json = "{baseName:'Base',subName:'SubRevised'}";
|
||||
Base base = gson.fromJson(json, Base.class);
|
||||
|
@ -73,12 +67,9 @@ public class InstanceCreatorTest extends TestCase {
|
|||
|
||||
public void testInstanceCreatorReturnsSubTypeForField() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new InstanceCreator<Base>() {
|
||||
@Override public Base createInstance(Type type) {
|
||||
return new Sub();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (InstanceCreator<Base>) type -> new Sub())
|
||||
.create();
|
||||
String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
|
||||
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
|
||||
assertTrue(target.base instanceof Sub);
|
||||
|
|
|
@ -65,7 +65,7 @@ public class InternationalizationTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testStringsWithUnicodeChineseCharactersEscapedDeserialization() throws Exception {
|
||||
String actual = gson.fromJson("'\\u597d\\u597d\\u597d'", String.class);
|
||||
String actual = gson.fromJson("\"\\u597d\\u597d\\u597d\"", String.class);
|
||||
assertEquals("\u597d\u597d\u597d", actual);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public class JavaUtilConcurrentAtomicTest extends TestCase {
|
|||
Gson gson = new GsonBuilder()
|
||||
.setLongSerializationPolicy(LongSerializationPolicy.STRING)
|
||||
.create();
|
||||
AtomicLongHolder target = gson.fromJson("{'value':'10'}", AtomicLongHolder.class);
|
||||
AtomicLongHolder target = gson.fromJson("{\"value\":\"10\"}", AtomicLongHolder.class);
|
||||
assertEquals(10, target.value.get());
|
||||
String json = gson.toJson(target);
|
||||
assertEquals("{\"value\":\"10\"}", json);
|
||||
|
@ -95,7 +95,7 @@ public class JavaUtilConcurrentAtomicTest extends TestCase {
|
|||
Gson gson = new GsonBuilder()
|
||||
.setLongSerializationPolicy(LongSerializationPolicy.STRING)
|
||||
.create();
|
||||
AtomicLongArray target = gson.fromJson("['10', '13', '14']", AtomicLongArray.class);
|
||||
AtomicLongArray target = gson.fromJson("[\"10\", \"13\", \"14\"]", AtomicLongArray.class);
|
||||
assertEquals(3, target.length());
|
||||
assertEquals(10, target.get(0));
|
||||
assertEquals(13, target.get(1));
|
||||
|
|
|
@ -36,7 +36,7 @@ public class JavaUtilTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testCurrency() throws Exception {
|
||||
CurrencyHolder target = gson.fromJson("{'value':'USD'}", CurrencyHolder.class);
|
||||
CurrencyHolder target = gson.fromJson("{\"value\":\"USD\"}", CurrencyHolder.class);
|
||||
assertEquals("USD", target.value.getCurrencyCode());
|
||||
String json = gson.toJson(target);
|
||||
assertEquals("{\"value\":\"USD\"}", json);
|
||||
|
@ -52,7 +52,7 @@ public class JavaUtilTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testProperties() {
|
||||
Properties props = gson.fromJson("{'a':'v1','b':'v2'}", Properties.class);
|
||||
Properties props = gson.fromJson("{\"a\":\"v1\",\"b\":\"v2\"}", Properties.class);
|
||||
assertEquals("v1", props.getProperty("a"));
|
||||
assertEquals("v2", props.getProperty("b"));
|
||||
String json = gson.toJson(props);
|
||||
|
|
|
@ -49,7 +49,7 @@ public final class JsonAdapterAnnotationOnClassesTest extends TestCase {
|
|||
// Also invoke the JsonAdapter javadoc sample
|
||||
json = gson.toJson(new User("Inderjeet", "Singh"));
|
||||
assertEquals("{\"name\":\"Inderjeet Singh\"}", json);
|
||||
User user = gson.fromJson("{'name':'Joel Leitch'}", User.class);
|
||||
User user = gson.fromJson("{\"name\":\"Joel Leitch\"}", User.class);
|
||||
assertEquals("Joel", user.firstName);
|
||||
assertEquals("Leitch", user.lastName);
|
||||
|
||||
|
@ -94,6 +94,7 @@ public final class JsonAdapterAnnotationOnClassesTest extends TestCase {
|
|||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(A.class, serializer)
|
||||
.create();
|
||||
String json = gson.toJson(new A("abcd"));
|
||||
|
@ -113,6 +114,7 @@ public final class JsonAdapterAnnotationOnClassesTest extends TestCase {
|
|||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(A.class, deserializer)
|
||||
.create();
|
||||
String json = gson.toJson(new A("abcd"));
|
||||
|
|
|
@ -57,12 +57,13 @@ public final class JsonAdapterAnnotationOnFieldsTest extends TestCase {
|
|||
.create();
|
||||
String json = gson.toJson(new Computer(new User("Inderjeet Singh")));
|
||||
assertEquals("{\"user\":\"RegisteredUserAdapter\"}", json);
|
||||
Computer computer = gson.fromJson("{'user':'Inderjeet Singh'}", Computer.class);
|
||||
Computer computer = gson.fromJson("{\"user\":\"Inderjeet Singh\"}", Computer.class);
|
||||
assertEquals("RegisteredUserAdapter", computer.user.name);
|
||||
}
|
||||
|
||||
public void testFieldAnnotationTakesPrecedenceOverRegisteredTypeAdapter() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Part.class, new TypeAdapter<Part>() {
|
||||
@Override public void write(JsonWriter out, Part part) throws IOException {
|
||||
throw new AssertionError();
|
||||
|
|
|
@ -16,13 +16,7 @@
|
|||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.common.TestTypes.BagOfPrimitives;
|
||||
import com.google.gson.common.TestTypes.Nested;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
@ -123,9 +117,9 @@ public class JsonParserTest extends TestCase {
|
|||
|
||||
public void testExtraCommasInArrays() {
|
||||
Type type = new TypeToken<List<String>>() {}.getType();
|
||||
assertEquals(Arrays.asList("a", null, "b", null, null), gson.fromJson("[a,,b,,]", type));
|
||||
assertEquals(Arrays.asList(null, null), gson.fromJson("[,]", type));
|
||||
assertEquals(Arrays.asList("a", null), gson.fromJson("[a,]", type));
|
||||
assertEquals(Arrays.asList("a", "b"), gson.fromJson("[a,,b,,]", type));
|
||||
assertEquals(Arrays.asList(), gson.fromJson("[,]", type));
|
||||
assertEquals(Arrays.asList("a"), gson.fromJson("[a,]", type));
|
||||
}
|
||||
|
||||
public void testExtraCommasInMaps() {
|
||||
|
|
|
@ -33,7 +33,7 @@ public class LeniencyTest extends TestCase {
|
|||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gson = new GsonBuilder().setLenient().create();
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
public void testLenientFromJson() {
|
||||
|
|
|
@ -106,7 +106,7 @@ public class MapAsArrayTypeAdapterTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testMapWithTypeVariableDeserialization() {
|
||||
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
|
||||
Gson gson = new GsonBuilder().setLenient().enableComplexMapKeySerialization().create();
|
||||
String json = "{map:[[{x:2,y:3},{x:4,y:5}]]}";
|
||||
Type type = new TypeToken<PointWithProperty<Point>>(){}.getType();
|
||||
PointWithProperty<Point> map = gson.fromJson(json, type);
|
||||
|
|
|
@ -155,7 +155,7 @@ public class MapTest extends TestCase {
|
|||
assertEquals(123, map.get("null").intValue());
|
||||
assertNull(map.get(null));
|
||||
|
||||
map = gson.fromJson("{null:123}", typeOfMap);
|
||||
map = gson.fromJson("{'null':123}", typeOfMap);
|
||||
assertEquals(1, map.size());
|
||||
assertEquals(123, map.get("null").intValue());
|
||||
assertNull(map.get(null));
|
||||
|
|
|
@ -99,7 +99,7 @@ public class NullObjectAndFieldTest extends TestCase {
|
|||
*/
|
||||
public void testNullWrappedPrimitiveMemberDeserialization() {
|
||||
Gson gson = gsonBuilder.create();
|
||||
String json = "{'value':null}";
|
||||
String json = "{\"value\":null}";
|
||||
ClassWithNullWrappedPrimitive target = gson.fromJson(json, ClassWithNullWrappedPrimitive.class);
|
||||
assertNull(target.value);
|
||||
}
|
||||
|
@ -223,12 +223,8 @@ public class NullObjectAndFieldTest extends TestCase {
|
|||
|
||||
public void testCustomTypeAdapterPassesNullDesrialization() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(ObjectWithField.class, new JsonDeserializer<ObjectWithField>() {
|
||||
@Override public ObjectWithField deserialize(JsonElement json, Type type,
|
||||
JsonDeserializationContext context) {
|
||||
return context.deserialize(null, type);
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(ObjectWithField.class, (JsonDeserializer<ObjectWithField>) (json, type, context) -> context.deserialize(null, type)).create();
|
||||
String json = "{value:'value1'}";
|
||||
ObjectWithField target = gson.fromJson(json, ObjectWithField.class);
|
||||
assertNull(target);
|
||||
|
|
|
@ -346,7 +346,7 @@ public class ObjectTest extends TestCase {
|
|||
return p.new Child();
|
||||
}
|
||||
}).create();
|
||||
String json = "{'value2':3}";
|
||||
String json = "{\"value2\":3}";
|
||||
Parent.Child c = gson.fromJson(json, Parent.Child.class);
|
||||
assertEquals(3, c.value2);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* Functional tests for Java Character values.
|
||||
*
|
||||
|
|
|
@ -18,11 +18,7 @@ package com.google.gson.functional;
|
|||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.LongSerializationPolicy;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.internal.LazilyParsedNumber;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.Serializable;
|
||||
|
@ -95,7 +91,7 @@ public class PrimitiveTest extends TestCase {
|
|||
gson.fromJson("2147483648", byte.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException e) {
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 path $", e.getMessage());
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 (char '\0') path $", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +129,7 @@ public class PrimitiveTest extends TestCase {
|
|||
gson.fromJson("2147483648", short.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException e) {
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 path $", e.getMessage());
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 (char '\0') path $", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,7 +431,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDoubleNaNSerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
double nan = Double.NaN;
|
||||
assertEquals("NaN", gson.toJson(nan));
|
||||
assertEquals("NaN", gson.toJson(Double.NaN));
|
||||
|
@ -461,7 +457,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testFloatNaNSerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
float nan = Float.NaN;
|
||||
assertEquals("NaN", gson.toJson(nan));
|
||||
assertEquals("NaN", gson.toJson(Float.NaN));
|
||||
|
@ -495,7 +491,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDoubleInfinitySerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
double infinity = Double.POSITIVE_INFINITY;
|
||||
assertEquals("Infinity", gson.toJson(infinity));
|
||||
assertEquals("Infinity", gson.toJson(Double.POSITIVE_INFINITY));
|
||||
|
@ -521,7 +517,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testFloatInfinitySerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
float infinity = Float.POSITIVE_INFINITY;
|
||||
assertEquals("Infinity", gson.toJson(infinity));
|
||||
assertEquals("Infinity", gson.toJson(Float.POSITIVE_INFINITY));
|
||||
|
@ -555,7 +551,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNegativeInfinitySerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
double negativeInfinity = Double.NEGATIVE_INFINITY;
|
||||
assertEquals("-Infinity", gson.toJson(negativeInfinity));
|
||||
assertEquals("-Infinity", gson.toJson(Double.NEGATIVE_INFINITY));
|
||||
|
@ -581,7 +577,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNegativeInfinityFloatSerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
float negativeInfinity = Float.NEGATIVE_INFINITY;
|
||||
assertEquals("-Infinity", gson.toJson(negativeInfinity));
|
||||
assertEquals("-Infinity", gson.toJson(Float.NEGATIVE_INFINITY));
|
||||
|
@ -633,9 +629,9 @@ public class PrimitiveTest extends TestCase {
|
|||
|
||||
String value = "String Blah Blah Blah...1, 2, 3";
|
||||
try {
|
||||
gson.fromJson(value, String.class);
|
||||
new Gson().fromJson(value, String.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException expected) { }
|
||||
} catch (JsonIOException expected) { }
|
||||
}
|
||||
|
||||
public void testHtmlCharacterSerialization() throws Exception {
|
||||
|
|
|
@ -38,7 +38,7 @@ public class SecurityTest extends TestCase {
|
|||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gsonBuilder = new GsonBuilder();
|
||||
gsonBuilder = new GsonBuilder().setLenient();
|
||||
}
|
||||
|
||||
public void testNonExecutableJsonSerialization() {
|
||||
|
|
|
@ -159,7 +159,7 @@ public final class StreamingTypeAdaptersTest extends TestCase {
|
|||
out.value(person.name + "," + person.age);
|
||||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(
|
||||
Gson gson = new GsonBuilder().setLenient().registerTypeAdapter(
|
||||
Person.class, typeAdapter).create();
|
||||
Truck truck = new Truck();
|
||||
truck.horsePower = 1.0D;
|
||||
|
@ -175,7 +175,7 @@ public final class StreamingTypeAdaptersTest extends TestCase {
|
|||
gson.fromJson(json, Truck.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException expected) {}
|
||||
gson = new GsonBuilder().registerTypeAdapter(Person.class, typeAdapter.nullSafe()).create();
|
||||
gson = new GsonBuilder().setLenient().registerTypeAdapter(Person.class, typeAdapter.nullSafe()).create();
|
||||
assertEquals("{\"horsePower\":1.0,\"passengers\":[null,\"jesse,30\"]}",
|
||||
gson.toJson(truck, Truck.class));
|
||||
truck = gson.fromJson(json, Truck.class);
|
||||
|
|
|
@ -54,6 +54,7 @@ public class TreeTypeAdaptersTest extends TestCase {
|
|||
@Override
|
||||
protected void setUp() {
|
||||
gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Id.class, new IdTreeTypeAdapter())
|
||||
.create();
|
||||
course = new Course<>(COURSE_ID, 4,
|
||||
|
|
|
@ -34,6 +34,7 @@ import junit.framework.TestCase;
|
|||
public final class TypeAdapterPrecedenceTest extends TestCase {
|
||||
public void testNonstreamingFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer 1"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer 2"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer 1"))
|
||||
|
@ -45,6 +46,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testStreamingFollowedByStreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter 1"))
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter 2"))
|
||||
.create();
|
||||
|
@ -54,6 +56,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testSerializeNonstreamingTypeAdapterFollowedByStreamingTypeAdapter() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
|
@ -64,6 +67,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testStreamingFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
|
@ -74,6 +78,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testStreamingHierarchicalFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeHierarchyAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
|
@ -89,11 +94,12 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
.registerTypeHierarchyAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
.create();
|
||||
assertEquals("\"foo via type adapter\"", gson.toJson(new Foo("foo")));
|
||||
assertEquals("foo via type adapter", gson.fromJson("foo", Foo.class).name);
|
||||
assertEquals("foo via type adapter", gson.fromJson("\"foo\"", Foo.class).name);
|
||||
}
|
||||
|
||||
public void testStreamingHierarchicalFollowedByNonstreamingHierarchical() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeHierarchyAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeHierarchyAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
.registerTypeHierarchyAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
|
@ -104,6 +110,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testNonstreamingHierarchicalFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeHierarchyAdapter(Foo.class, newSerializer("hierarchical"))
|
||||
.registerTypeHierarchyAdapter(Foo.class, newDeserializer("hierarchical"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("non hierarchical"))
|
||||
|
|
|
@ -52,7 +52,7 @@ public class SqlTypesGsonTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultSqlDateDeserialization() {
|
||||
String json = "'Dec 3, 2009'";
|
||||
String json = "\"Dec 3, 2009\"";
|
||||
java.sql.Date extracted = gson.fromJson(json, java.sql.Date.class);
|
||||
DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class SqlTypesGsonTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultSqlTimeDeserialization() {
|
||||
String json = "'1:18:02 PM'";
|
||||
String json = "\"1:18:02 PM\"";
|
||||
Time extracted = gson.fromJson(json, Time.class);
|
||||
DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class SqlTypesGsonTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultSqlTimestampDeserialization() {
|
||||
String json = "'Dec 3, 2009 1:18:02 PM'";
|
||||
String json = "\"Dec 3, 2009 1:18:02 PM\"";
|
||||
Timestamp extracted = gson.fromJson(json, Timestamp.class);
|
||||
DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
|
||||
DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.gson;
|
||||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -39,7 +40,7 @@ public final class CommentsTest extends TestCase {
|
|||
+ " \"c\"\n"
|
||||
+ "]";
|
||||
|
||||
List<String> abc = new Gson().fromJson(json, new TypeToken<List<String>>() {}.getType());
|
||||
List<String> abc = new GsonBuilder().setLenient().create().fromJson(json, new TypeToken<List<String>>() {}.getType());
|
||||
assertEquals(Arrays.asList("a", "b", "c"), abc);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ExtraAssert {
|
||||
public static <T> void assertListEquals(List<T> expecteds, List<T> actuals) {
|
||||
TestCase.assertNotNull(expecteds);
|
||||
TestCase.assertNotNull(actuals);
|
||||
TestCase.assertEquals(expecteds.size(), actuals.size());
|
||||
for (int i = 0; i < expecteds.size(); i++) {
|
||||
TestCase.assertEquals(expecteds.get(i), actuals.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringArrayBox {
|
||||
public String[] collection;
|
||||
}
|
||||
|
||||
public static class StringListBox {
|
||||
public List<String> collection;
|
||||
}
|
||||
|
||||
public static class IntListBox {
|
||||
public List<Integer> collection;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.*;
|
||||
|
||||
public class Json5Test extends TestCase {
|
||||
public void testShortExample() {
|
||||
// Taken from the official example
|
||||
assertTrue(new Gson().fromJson("{\n" +
|
||||
" // comments\n" +
|
||||
" unquoted: 'and you can quote me on that',\n" +
|
||||
" singleQuotes: 'I can use \"double quotes\" here',\n" +
|
||||
" lineBreaks: \"Look, Mom! \\\n" +
|
||||
"No \\\\n's!\",\n" +
|
||||
" hexadecimal: 0xdecaf,\n" +
|
||||
" leadingDecimalPoint: .8675309, andTrailing: 8675309.,\n" +
|
||||
" positiveSign: +1,\n" +
|
||||
" trailingComma: 'in objects', andIn: ['arrays',],\n" +
|
||||
" \"backwardsCompatible\": \"with JSON\",\n" +
|
||||
"}", ExampleModel.class).isDefault());
|
||||
}
|
||||
|
||||
public static class ExampleModel {
|
||||
public String unquoted;
|
||||
public String singleQuotes;
|
||||
public String lineBreaks;
|
||||
public Integer hexadecimal;
|
||||
public Double leadingDecimalPoint;
|
||||
public Double andTrailing;
|
||||
public Integer positiveSign;
|
||||
public String trailingComma;
|
||||
public String[] andIn;
|
||||
public String backwardsCompatible;
|
||||
|
||||
public boolean isDefault() {
|
||||
return unquoted.equals("and you can quote me on that")
|
||||
&& singleQuotes.equals("I can use \"double quotes\" here")
|
||||
&& lineBreaks.equals("Look, Mom!\nNo \\n's!")
|
||||
&& hexadecimal.equals(0xdecaf)
|
||||
&& leadingDecimalPoint.equals(.8675309)
|
||||
&& andTrailing.equals(8675309.)
|
||||
&& positiveSign.equals(1)
|
||||
&& trailingComma.equals("in objects")
|
||||
&& andIn.length == 1 && andIn[0].equals("arrays")
|
||||
&& backwardsCompatible.equals("with JSON");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.TestCase;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.gson.jf.ExtraAssert.*;
|
||||
|
||||
public class LenientCollectionCommaTest extends TestCase {
|
||||
private Gson lenient;
|
||||
private static final String json = "{\"collection\": [1, 2,, 3, , , 4, 5,]}";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
lenient = new GsonBuilder().setLenient().create();
|
||||
}
|
||||
|
||||
public void testElementSkipping() {
|
||||
assertListEquals(List.of(1, 2, 3, 4, 5), lenient.fromJson(json, IntListBox.class).collection);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.TestCase;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static com.google.gson.jf.ExtraAssert.*;
|
||||
|
||||
public class LenientCollectionTest extends TestCase {
|
||||
private Gson lenient;
|
||||
private Gson strict;
|
||||
private static final String json = "{\"collection\": \"example\"}";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
lenient = new GsonBuilder().setLenient().create();
|
||||
strict = new GsonBuilder().create();
|
||||
}
|
||||
|
||||
public void testLenientArray() {
|
||||
assertArrayEquals(new String[] {"example"}, lenient.fromJson(json, StringArrayBox.class).collection);
|
||||
}
|
||||
|
||||
public void testLenientList() {
|
||||
assertListEquals(List.of("example"), lenient.fromJson(json, StringListBox.class).collection);
|
||||
}
|
||||
|
||||
public void testStrictArray() {
|
||||
try {
|
||||
strict.fromJson(json, StringArrayBox.class);
|
||||
fail("Strict Gson should not deserialize array without brackets");
|
||||
} catch (JsonParseException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testStrictList() {
|
||||
try {
|
||||
strict.fromJson(json, StringListBox.class);
|
||||
fail("Strict Gson should not deserialize list without brackets");
|
||||
} catch (JsonParseException expected) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.gson.jf.ExtraAssert.*;
|
||||
|
||||
public class OmitQuotesTest extends TestCase {
|
||||
private Gson lenient;
|
||||
private Gson strict;
|
||||
private static final String lenientJson = "{collection:[\"example\"]}";
|
||||
private static final String strictJson = "{\"collection\":[\"example\"]}";
|
||||
private StringListBox slb;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
lenient = new GsonBuilder().setOmitQuotes().create();
|
||||
strict = new GsonBuilder().create();
|
||||
slb = new StringListBox();
|
||||
slb.collection = List.of("example");
|
||||
}
|
||||
|
||||
public void testLenient() {
|
||||
assertEquals(lenientJson, lenient.toJson(slb));
|
||||
}
|
||||
|
||||
public void testStrict() {
|
||||
assertEquals(strictJson, strict.toJson(slb));
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ public class JsonAdapterNullSafeTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNullSafeBugDeserialize() throws Exception {
|
||||
Device device = gson.fromJson("{'id':'ec57803e2'}", Device.class);
|
||||
Device device = gson.fromJson("{\"id\":\"ec57803e2\"}", Device.class);
|
||||
assertEquals("ec57803e2", device.id);
|
||||
}
|
||||
|
||||
|
|
|
@ -1172,7 +1172,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(reader("[,]"));
|
||||
|
@ -1189,14 +1189,14 @@ public final class JsonReaderTest extends TestCase {
|
|||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(reader("[,true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.endArray();
|
||||
|
||||
|
@ -1204,14 +1204,14 @@ public final class JsonReaderTest extends TestCase {
|
|||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(reader("[,]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
reader.nextNull();
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
//reader.nextNull();
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
try {
|
||||
reader.skipValue();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(reader("[,]"));
|
||||
|
@ -1379,46 +1379,46 @@ public final class JsonReaderTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testFailWithPosition() throws IOException {
|
||||
testFailWithPosition("Expected value at line 6 column 5 path $[1]",
|
||||
testFailWithPosition("Expected value at line 6 column 5 (char '}') path $[1]",
|
||||
"[\n\n\n\n\n\"a\",}]");
|
||||
}
|
||||
|
||||
public void testFailWithPositionGreaterThanBufferSize() throws IOException {
|
||||
String spaces = repeat(' ', 8192);
|
||||
testFailWithPosition("Expected value at line 6 column 5 path $[1]",
|
||||
testFailWithPosition("Expected value at line 6 column 5 (char '}') path $[1]",
|
||||
"[\n\n" + spaces + "\n\n\n\"a\",}]");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverSlashSlashEndOfLineComment() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 6 path $[1]",
|
||||
testFailWithPosition("Expected value at line 5 column 6 (char '}') path $[1]",
|
||||
"\n// foo\n\n//bar\r\n[\"a\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverHashEndOfLineComment() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 6 path $[1]",
|
||||
testFailWithPosition("Expected value at line 5 column 6 (char '}') path $[1]",
|
||||
"\n# foo\n\n#bar\r\n[\"a\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverCStyleComment() throws IOException {
|
||||
testFailWithPosition("Expected value at line 6 column 12 path $[1]",
|
||||
testFailWithPosition("Expected value at line 6 column 12 (char '}') path $[1]",
|
||||
"\n\n/* foo\n*\n*\r\nbar */[\"a\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverQuotedString() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 3 path $[1]",
|
||||
testFailWithPosition("Expected value at line 5 column 3 (char '}') path $[1]",
|
||||
"[\"foo\nbar\r\nbaz\n\",\n }");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverUnquotedString() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 2 path $[1]", "[\n\nabcd\n\n,}");
|
||||
testFailWithPosition("Expected value at line 5 column 2 (char '}') path $[1]", "[\n\nabcd\n\n,}");
|
||||
}
|
||||
|
||||
public void testFailWithEscapedNewlineCharacter() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 3 path $[1]", "[\n\n\"\\\n\n\",}");
|
||||
testFailWithPosition("Expected value at line 5 column 3 (char '}') path $[1]", "[\n\n\"\\\n\n\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionIsOffsetByBom() throws IOException {
|
||||
testFailWithPosition("Expected value at line 1 column 6 path $[1]",
|
||||
testFailWithPosition("Expected value at line 1 column 6 (char '}') path $[1]",
|
||||
"\ufeff[\"a\",}]");
|
||||
}
|
||||
|
||||
|
@ -1461,7 +1461,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
reader.peek();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
assertEquals("Expected value at line 1 column 14 path $[1].a[2]", expected.getMessage());
|
||||
assertEquals("Expected value at line 1 column 14 (char '}') path $[1].a[2]", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1728,7 +1728,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
assertDocument("{\"name\"=>\"string\",", BEGIN_OBJECT, NAME, STRING, IOException.class);
|
||||
assertDocument("{\"name\"=>\"string\",\"name\"", BEGIN_OBJECT, NAME, STRING, NAME);
|
||||
assertDocument("[}", BEGIN_ARRAY, IOException.class);
|
||||
assertDocument("[,]", BEGIN_ARRAY, NULL, NULL, END_ARRAY);
|
||||
assertDocument("[,]", BEGIN_ARRAY, END_ARRAY);
|
||||
assertDocument("{", BEGIN_OBJECT, IOException.class);
|
||||
assertDocument("{\"name\"", BEGIN_OBJECT, NAME, IOException.class);
|
||||
assertDocument("{\"name\",", BEGIN_OBJECT, NAME, IOException.class);
|
||||
|
|
Loading…
Reference in New Issue