Added special serialization of "Long". Now the client has the ability to output a long field as a JSON "String". This is useful for JavaScript clients that need to handle long values.

As well, this change does a major clean up of the custom type adapter handling and ParameterizedTypeMap creation.
This commit is contained in:
Joel Leitch 2008-12-28 03:23:36 +00:00
parent 859af0025c
commit 458f2baa2f
5 changed files with 128 additions and 57 deletions

View File

@ -53,7 +53,8 @@ import java.util.UUID;
final class DefaultTypeAdapters { final class DefaultTypeAdapters {
private static final DefaultDateTypeAdapter DATE_TYPE_ADAPTER = private static final DefaultDateTypeAdapter DATE_TYPE_ADAPTER =
new DefaultDateTypeAdapter(DateFormat.getDateTimeInstance()); new DefaultDateTypeAdapter(DateFormat.getDateTimeInstance());
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter(); private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter();
private static final UrlTypeAdapter URL_TYPE_ADAPTER = new UrlTypeAdapter(); private static final UrlTypeAdapter URL_TYPE_ADAPTER = new UrlTypeAdapter();
@ -68,10 +69,10 @@ final class DefaultTypeAdapters {
private static final BooleanTypeAdapter BOOLEAN_TYPE_ADAPTER = new BooleanTypeAdapter(); private static final BooleanTypeAdapter BOOLEAN_TYPE_ADAPTER = new BooleanTypeAdapter();
private static final ByteTypeAdapter BYTE_TYPE_ADAPTER = new ByteTypeAdapter(); private static final ByteTypeAdapter BYTE_TYPE_ADAPTER = new ByteTypeAdapter();
private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter(); private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter();
private static final DoubleTypeAdapter DOUBLE_TYPE_ADAPTER = new DoubleTypeAdapter(); private static final DoubleDeserializer DOUBLE_TYPE_ADAPTER = new DoubleDeserializer();
private static final FloatDeserializer FLOAT_TYPE_ADAPTER = new FloatDeserializer(); private static final FloatDeserializer FLOAT_TYPE_ADAPTER = new FloatDeserializer();
private static final IntegerTypeAdapter INTEGER_TYPE_ADAPTER = new IntegerTypeAdapter(); private static final IntegerTypeAdapter INTEGER_TYPE_ADAPTER = new IntegerTypeAdapter();
private static final LongTypeAdapter LONG_TYPE_ADAPTER = new LongTypeAdapter(); private static final LongDeserializer LONG_DESERIALIZER = new LongDeserializer();
private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter(); private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter();
private static final ShortTypeAdapter SHORT_TYPE_ADAPTER = new ShortTypeAdapter(); private static final ShortTypeAdapter SHORT_TYPE_ADAPTER = new ShortTypeAdapter();
private static final StringTypeAdapter STRING_TYPE_ADAPTER = new StringTypeAdapter(); private static final StringTypeAdapter STRING_TYPE_ADAPTER = new StringTypeAdapter();
@ -81,16 +82,16 @@ final class DefaultTypeAdapters {
// The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS // The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS
// must be defined after the constants for the type adapters. Otherwise, the type adapter // must be defined after the constants for the type adapters. Otherwise, the type adapter
// constants will appear as nulls. // constants will appear as nulls.
static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS = private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
getDefaultSerializers(); createDefaultSerializers();
static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS = private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
getDefaultDeserializers(); createDefaultDeserializers();
static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS = private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
getDefaultInstanceCreators(); createDefaultInstanceCreators();
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers() { private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultSerializers() {
ParameterizedTypeHandlerMap<JsonSerializer<?>> map = ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
new ParameterizedTypeHandlerMap<JsonSerializer<?>>(); new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
map.register(Enum.class, ENUM_TYPE_ADAPTER); map.register(Enum.class, ENUM_TYPE_ADAPTER);
map.register(URL.class, URL_TYPE_ADAPTER); map.register(URL.class, URL_TYPE_ADAPTER);
@ -112,8 +113,6 @@ final class DefaultTypeAdapters {
map.register(char.class, CHARACTER_TYPE_ADAPTER); map.register(char.class, CHARACTER_TYPE_ADAPTER);
map.register(Integer.class, INTEGER_TYPE_ADAPTER); map.register(Integer.class, INTEGER_TYPE_ADAPTER);
map.register(int.class, INTEGER_TYPE_ADAPTER); map.register(int.class, INTEGER_TYPE_ADAPTER);
map.register(Long.class, LONG_TYPE_ADAPTER);
map.register(long.class, LONG_TYPE_ADAPTER);
map.register(Number.class, NUMBER_TYPE_ADAPTER); map.register(Number.class, NUMBER_TYPE_ADAPTER);
map.register(Short.class, SHORT_TYPE_ADAPTER); map.register(Short.class, SHORT_TYPE_ADAPTER);
map.register(short.class, SHORT_TYPE_ADAPTER); map.register(short.class, SHORT_TYPE_ADAPTER);
@ -123,9 +122,9 @@ final class DefaultTypeAdapters {
return map; return map;
} }
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> getDefaultDeserializers() { private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() {
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map = ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>(); new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
map.register(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER)); map.register(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER));
map.register(URL.class, wrapDeserializer(URL_TYPE_ADAPTER)); map.register(URL.class, wrapDeserializer(URL_TYPE_ADAPTER));
map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER)); map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER));
@ -150,8 +149,8 @@ final class DefaultTypeAdapters {
map.register(float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER)); map.register(float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER));
map.register(Integer.class, wrapDeserializer(INTEGER_TYPE_ADAPTER)); map.register(Integer.class, wrapDeserializer(INTEGER_TYPE_ADAPTER));
map.register(int.class, wrapDeserializer(INTEGER_TYPE_ADAPTER)); map.register(int.class, wrapDeserializer(INTEGER_TYPE_ADAPTER));
map.register(Long.class, wrapDeserializer(LONG_TYPE_ADAPTER)); map.register(Long.class, wrapDeserializer(LONG_DESERIALIZER));
map.register(long.class, wrapDeserializer(LONG_TYPE_ADAPTER)); map.register(long.class, wrapDeserializer(LONG_DESERIALIZER));
map.register(Number.class, wrapDeserializer(NUMBER_TYPE_ADAPTER)); map.register(Number.class, wrapDeserializer(NUMBER_TYPE_ADAPTER));
map.register(Short.class, wrapDeserializer(SHORT_TYPE_ADAPTER)); map.register(Short.class, wrapDeserializer(SHORT_TYPE_ADAPTER));
map.register(short.class, wrapDeserializer(SHORT_TYPE_ADAPTER)); map.register(short.class, wrapDeserializer(SHORT_TYPE_ADAPTER));
@ -161,7 +160,7 @@ final class DefaultTypeAdapters {
return map; return map;
} }
private static ParameterizedTypeHandlerMap<InstanceCreator<?>> getDefaultInstanceCreators() { private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() {
ParameterizedTypeHandlerMap<InstanceCreator<?>> map = ParameterizedTypeHandlerMap<InstanceCreator<?>> map =
new ParameterizedTypeHandlerMap<InstanceCreator<?>>(); new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
map.register(Enum.class, ENUM_TYPE_ADAPTER); map.register(Enum.class, ENUM_TYPE_ADAPTER);
@ -183,16 +182,43 @@ final class DefaultTypeAdapters {
return new JsonDeserializerExceptionWrapper(deserializer); return new JsonDeserializerExceptionWrapper(deserializer);
} }
static void registerSerializersForFloatingPoints(boolean serializeSpecialFloatingPointValues, static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers() {
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers) { return getDefaultSerializers(false, false);
}
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers(
boolean serializeSpecialFloatingPointValues, boolean serializeLongsAsString) {
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers =
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
// Double primitive
DefaultTypeAdapters.DoubleSerializer doubleSerializer = DefaultTypeAdapters.DoubleSerializer doubleSerializer =
new DefaultTypeAdapters.DoubleSerializer(serializeSpecialFloatingPointValues); new DefaultTypeAdapters.DoubleSerializer(serializeSpecialFloatingPointValues);
DefaultTypeAdapters.FloatSerializer floatSerializer =
new DefaultTypeAdapters.FloatSerializer(serializeSpecialFloatingPointValues);
serializers.registerIfAbsent(Double.class, doubleSerializer); serializers.registerIfAbsent(Double.class, doubleSerializer);
serializers.registerIfAbsent(double.class, doubleSerializer); serializers.registerIfAbsent(double.class, doubleSerializer);
// Float primitive
DefaultTypeAdapters.FloatSerializer floatSerializer =
new DefaultTypeAdapters.FloatSerializer(serializeSpecialFloatingPointValues);
serializers.registerIfAbsent(Float.class, floatSerializer); serializers.registerIfAbsent(Float.class, floatSerializer);
serializers.registerIfAbsent(float.class, floatSerializer); serializers.registerIfAbsent(float.class, floatSerializer);
// Long primitive
DefaultTypeAdapters.LongSerializer longSerializer =
new DefaultTypeAdapters.LongSerializer(serializeLongsAsString);
serializers.registerIfAbsent(Long.class, longSerializer);
serializers.registerIfAbsent(long.class, longSerializer);
serializers.registerIfAbsent(DEFAULT_SERIALIZERS);
return serializers;
}
static ParameterizedTypeHandlerMap<JsonDeserializer<?>> getDefaultDeserializers() {
return DEFAULT_DESERIALIZERS;
}
static ParameterizedTypeHandlerMap<InstanceCreator<?>> getDefaultInstanceCreators() {
return DEFAULT_INSTANCE_CREATORS;
} }
static class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> { static class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
@ -523,15 +549,34 @@ final class DefaultTypeAdapters {
@Override @Override
public String toString() { public String toString() {
return LongTypeAdapter.class.getSimpleName(); return NumberTypeAdapter.class.getSimpleName();
} }
} }
private static class LongTypeAdapter implements JsonSerializer<Long>, JsonDeserializer<Long> { private static class LongSerializer implements JsonSerializer<Long> {
public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) { private final boolean serializeAsString;
return new JsonPrimitive(src);
private LongSerializer(boolean serializeAsString) {
this.serializeAsString = serializeAsString;
} }
public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.createJsonNull();
} else if (serializeAsString) {
return new JsonPrimitive(String.valueOf(src));
} else {
return new JsonPrimitive(src);
}
}
@Override
public String toString() {
return LongSerializer.class.getSimpleName();
}
}
private static class LongDeserializer implements JsonDeserializer<Long> {
public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
return json.getAsLong(); return json.getAsLong();
@ -539,7 +584,7 @@ final class DefaultTypeAdapters {
@Override @Override
public String toString() { public String toString() {
return LongTypeAdapter.class.getSimpleName(); return LongDeserializer.class.getSimpleName();
} }
} }
@ -643,7 +688,7 @@ final class DefaultTypeAdapters {
} }
} }
private static class DoubleTypeAdapter implements JsonDeserializer<Double> { private static class DoubleDeserializer implements JsonDeserializer<Double> {
public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
return json.getAsDouble(); return json.getAsDouble();
@ -651,7 +696,7 @@ final class DefaultTypeAdapters {
@Override @Override
public String toString() { public String toString() {
return DoubleTypeAdapter.class.getSimpleName(); return DoubleDeserializer.class.getSimpleName();
} }
} }

View File

@ -142,9 +142,9 @@ public final class Gson {
*/ */
Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) { Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) {
this(strategy, fieldNamingPolicy, this(strategy, fieldNamingPolicy,
createObjectConstructor(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS), createObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
DEFAULT_JSON_FORMATTER, false, DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(),
getDefaultSerializers(), DefaultTypeAdapters.DEFAULT_DESERIALIZERS); DefaultTypeAdapters.getDefaultDeserializers());
} }
Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy, Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy,
@ -160,13 +160,6 @@ public final class Gson {
this.deserializers = deserializers; this.deserializers = deserializers;
} }
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers() {
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers =
DefaultTypeAdapters.DEFAULT_SERIALIZERS.copyOf();
DefaultTypeAdapters.registerSerializersForFloatingPoints(false, serializers);
return serializers;
}
static MappedObjectConstructor createObjectConstructor( static MappedObjectConstructor createObjectConstructor(
ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators) { ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators) {
MappedObjectConstructor objectConstructor = new MappedObjectConstructor(); MappedObjectConstructor objectConstructor = new MappedObjectConstructor();

View File

@ -52,6 +52,7 @@ import java.util.List;
public final class GsonBuilder { public final class GsonBuilder {
private double ignoreVersionsAfter; private double ignoreVersionsAfter;
private boolean serializeLongAsString;
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy; private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
private boolean serializeInnerClasses; private boolean serializeInnerClasses;
private final AnonymousAndLocalClassExclusionStrategy anonAndLocalClassExclusionStrategy; private final AnonymousAndLocalClassExclusionStrategy anonAndLocalClassExclusionStrategy;
@ -77,6 +78,7 @@ public final class GsonBuilder {
public GsonBuilder() { public GsonBuilder() {
// setup default values // setup default values
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS; ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
serializeLongAsString = false;
serializeInnerClasses = true; serializeInnerClasses = true;
anonAndLocalClassExclusionStrategy = new AnonymousAndLocalClassExclusionStrategy(); anonAndLocalClassExclusionStrategy = new AnonymousAndLocalClassExclusionStrategy();
innerClassExclusionStrategy = new InnerClassExclusionStrategy(); innerClassExclusionStrategy = new InnerClassExclusionStrategy();
@ -146,7 +148,19 @@ public final class GsonBuilder {
} }
/** /**
* Configures Gson to include or exclude inner classes * Configures Gson to output fields of type {@code long} as {@code String}s instead of a number.
*
* @param value the boolean value on whether or not {@code Gson} should serialize a {@code long}
* field as a {@code String}
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder serializeLongFieldsAsString(boolean value) {
serializeLongAsString = value;
return this;
}
/**
* Configures Gson to include or exclude inner classes.
* *
* @param value the boolean value on whether or not {@code Gson} should serialize inner classes * @param value the boolean value on whether or not {@code Gson} should serialize inner classes
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
@ -389,17 +403,17 @@ public final class GsonBuilder {
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf(); ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf(); ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers, addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers); customDeserializers);
customSerializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_SERIALIZERS);
DefaultTypeAdapters.registerSerializersForFloatingPoints(serializeSpecialFloatingPointValues, customSerializers.registerIfAbsent(DefaultTypeAdapters.getDefaultSerializers(
customSerializers); serializeSpecialFloatingPointValues, serializeLongAsString));
customDeserializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_DESERIALIZERS);
customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers());
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators = ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
instanceCreators.copyOf(); instanceCreators.copyOf();
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS); customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators());
MappedObjectConstructor objConstructor = Gson.createObjectConstructor(customInstanceCreators); MappedObjectConstructor objConstructor = Gson.createObjectConstructor(customInstanceCreators);
Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor, Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor,

View File

@ -73,13 +73,13 @@ public class ParameterizedTypesTest extends TestCase {
public void testTypesWithMultipleParametersSerialization() throws Exception { public void testTypesWithMultipleParametersSerialization() throws Exception {
MultiParameters<Integer, Float, Double, String, BagOfPrimitives> src = MultiParameters<Integer, Float, Double, String, BagOfPrimitives> src =
new MultiParameters<Integer, Float, Double, String, BagOfPrimitives>(10, 1.0F, 2.1D, new MultiParameters<Integer, Float, Double, String, BagOfPrimitives>(10, 1.0F, 2.1D,
"abc", new BagOfPrimitives()); "abc", new BagOfPrimitives());
Type typeOfSrc = new TypeToken<MultiParameters<Integer, Float, Double, String, Type typeOfSrc = new TypeToken<MultiParameters<Integer, Float, Double, String,
BagOfPrimitives>>() {}.getType(); BagOfPrimitives>>() {}.getType();
String json = gson.toJson(src, typeOfSrc); String json = gson.toJson(src, typeOfSrc);
String expected = "{\"a\":10,\"b\":1.0,\"c\":2.1,\"d\":\"abc\"," String expected = "{\"a\":10,\"b\":1.0,\"c\":2.1,\"d\":\"abc\","
+ "\"e\":{\"longValue\":0,\"intValue\":0,\"booleanValue\":false,\"stringValue\":\"\"}}"; + "\"e\":{\"longValue\":0,\"intValue\":0,\"booleanValue\":false,\"stringValue\":\"\"}}";
assertEquals(expected, json); assertEquals(expected, json);
} }
@ -87,12 +87,12 @@ public class ParameterizedTypesTest extends TestCase {
Type typeOfTarget = new TypeToken<MultiParameters<Integer, Float, Double, String, Type typeOfTarget = new TypeToken<MultiParameters<Integer, Float, Double, String,
BagOfPrimitives>>() {}.getType(); BagOfPrimitives>>() {}.getType();
String json = "{\"a\":10,\"b\":1.0,\"c\":2.1,\"d\":\"abc\"," String json = "{\"a\":10,\"b\":1.0,\"c\":2.1,\"d\":\"abc\","
+ "\"e\":{\"longValue\":0,\"intValue\":0,\"booleanValue\":false,\"stringValue\":\"\"}}"; + "\"e\":{\"longValue\":0,\"intValue\":0,\"booleanValue\":false,\"stringValue\":\"\"}}";
MultiParameters<Integer, Float, Double, String, BagOfPrimitives> target = MultiParameters<Integer, Float, Double, String, BagOfPrimitives> target =
gson.fromJson(json, typeOfTarget); gson.fromJson(json, typeOfTarget);
MultiParameters<Integer, Float, Double, String, BagOfPrimitives> expected = MultiParameters<Integer, Float, Double, String, BagOfPrimitives> expected =
new MultiParameters<Integer, Float, Double, String, BagOfPrimitives>(10, 1.0F, 2.1D, new MultiParameters<Integer, Float, Double, String, BagOfPrimitives>(10, 1.0F, 2.1D,
"abc", new BagOfPrimitives()); "abc", new BagOfPrimitives());
assertEquals(expected, target); assertEquals(expected, target);
} }

View File

@ -528,4 +528,23 @@ public class PrimitiveTest extends TestCase {
} catch (JsonParseException expected) { } catch (JsonParseException expected) {
} }
} }
public void testLongAsStringSerialization() throws Exception {
gson = new GsonBuilder().serializeLongFieldsAsString(true).create();
String result = gson.toJson(15L);
assertEquals("\"15\"", result);
// Test with an integer and ensure its still a number
result = gson.toJson(2);
assertEquals("2", result);
}
public void testLongAsStringDeserialization() throws Exception {
long value = gson.fromJson("\"15\"", long.class);
assertEquals(15, value);
gson = new GsonBuilder().serializeLongFieldsAsString(true).create();
value = gson.fromJson("\"25\"", long.class);
assertEquals(25, value);
}
} }