Add a type adapter for JsonElement, so it serializes just like everything else.
Fixes issue 362.
This commit is contained in:
parent
3a3870591e
commit
65df3b97ba
@ -248,6 +248,7 @@ public final class Gson {
|
|||||||
.typeAdapter(BigDecimal.class, new BigDecimalTypeAdapter())
|
.typeAdapter(BigDecimal.class, new BigDecimalTypeAdapter())
|
||||||
.typeAdapter(BigInteger.class, new BigIntegerTypeAdapter())
|
.typeAdapter(BigInteger.class, new BigIntegerTypeAdapter())
|
||||||
.factory(new CollectionTypeAdapterFactory(constructorConstructor))
|
.factory(new CollectionTypeAdapterFactory(constructorConstructor))
|
||||||
|
.factory(TypeAdapters.JSON_ELEMENT_FACTORY)
|
||||||
.factory(ObjectTypeAdapter.FACTORY);
|
.factory(ObjectTypeAdapter.FACTORY);
|
||||||
|
|
||||||
for (TypeAdapter.Factory factory : typeAdapterFactories) {
|
for (TypeAdapter.Factory factory : typeAdapterFactories) {
|
||||||
|
@ -16,27 +16,23 @@
|
|||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonNull;
|
import com.google.gson.JsonNull;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonPrimitive;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.internal.bind.TypeAdapters;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import com.google.gson.stream.MalformedJsonException;
|
import com.google.gson.stream.MalformedJsonException;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and writes GSON parse trees over streams.
|
* Reads and writes GSON parse trees over streams.
|
||||||
*/
|
*/
|
||||||
public final class Streams {
|
public final class Streams {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a reader in any state and returns the next value as a JsonElement.
|
* Takes a reader in any state and returns the next value as a JsonElement.
|
||||||
*/
|
*/
|
||||||
@ -45,7 +41,7 @@ public final class Streams {
|
|||||||
try {
|
try {
|
||||||
reader.peek();
|
reader.peek();
|
||||||
isEmpty = false;
|
isEmpty = false;
|
||||||
return parseRecursive(reader);
|
return TypeAdapters.JSON_ELEMENT.read(reader);
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
/*
|
/*
|
||||||
* For compatibility with JSON 1.5 and earlier, we return a JsonNull for
|
* For compatibility with JSON 1.5 and earlier, we return a JsonNull for
|
||||||
@ -64,79 +60,11 @@ public final class Streams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JsonElement parseRecursive(JsonReader reader) throws IOException {
|
|
||||||
switch (reader.peek()) {
|
|
||||||
case STRING:
|
|
||||||
return new JsonPrimitive(reader.nextString());
|
|
||||||
case NUMBER:
|
|
||||||
String number = reader.nextString();
|
|
||||||
return new JsonPrimitive(new LazilyParsedNumber(number));
|
|
||||||
case BOOLEAN:
|
|
||||||
return new JsonPrimitive(reader.nextBoolean());
|
|
||||||
case NULL:
|
|
||||||
reader.nextNull();
|
|
||||||
return JsonNull.INSTANCE;
|
|
||||||
case BEGIN_ARRAY:
|
|
||||||
JsonArray array = new JsonArray();
|
|
||||||
reader.beginArray();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
array.add(parseRecursive(reader));
|
|
||||||
}
|
|
||||||
reader.endArray();
|
|
||||||
return array;
|
|
||||||
case BEGIN_OBJECT:
|
|
||||||
JsonObject object = new JsonObject();
|
|
||||||
reader.beginObject();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
object.add(reader.nextName(), parseRecursive(reader));
|
|
||||||
}
|
|
||||||
reader.endObject();
|
|
||||||
return object;
|
|
||||||
case END_DOCUMENT:
|
|
||||||
case NAME:
|
|
||||||
case END_OBJECT:
|
|
||||||
case END_ARRAY:
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the JSON element to the writer, recursively.
|
* Writes the JSON element to the writer, recursively.
|
||||||
*/
|
*/
|
||||||
public static void write(JsonElement element, JsonWriter writer)
|
public static void write(JsonElement element, JsonWriter writer) throws IOException {
|
||||||
throws IOException {
|
TypeAdapters.JSON_ELEMENT.write(writer, element);
|
||||||
if (element == null || element.isJsonNull()) {
|
|
||||||
writer.nullValue();
|
|
||||||
} else if (element.isJsonPrimitive()) {
|
|
||||||
JsonPrimitive primitive = element.getAsJsonPrimitive();
|
|
||||||
if (primitive.isNumber()) {
|
|
||||||
writer.value(primitive.getAsNumber());
|
|
||||||
} else if (primitive.isBoolean()) {
|
|
||||||
writer.value(primitive.getAsBoolean());
|
|
||||||
} else {
|
|
||||||
writer.value(primitive.getAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (element.isJsonArray()) {
|
|
||||||
writer.beginArray();
|
|
||||||
for (JsonElement e : element.getAsJsonArray()) {
|
|
||||||
write(e, writer);
|
|
||||||
}
|
|
||||||
writer.endArray();
|
|
||||||
|
|
||||||
} else if (element.isJsonObject()) {
|
|
||||||
writer.beginObject();
|
|
||||||
for (Map.Entry<String, JsonElement> e : element.getAsJsonObject().entrySet()) {
|
|
||||||
JsonElement value = e.getValue();
|
|
||||||
writer.name(e.getKey());
|
|
||||||
write(value, writer);
|
|
||||||
}
|
|
||||||
writer.endObject();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Couldn't write " + element.getClass());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Writer writerForAppendable(Appendable appendable) {
|
public static Writer writerForAppendable(Appendable appendable) {
|
||||||
@ -183,4 +111,5 @@ public final class Streams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,12 @@
|
|||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
|
import com.google.gson.JsonNull;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.internal.LazilyParsedNumber;
|
import com.google.gson.internal.LazilyParsedNumber;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
@ -34,6 +39,7 @@ import java.util.Calendar;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -526,6 +532,81 @@ public final class TypeAdapters {
|
|||||||
|
|
||||||
public static final TypeAdapter.Factory LOCALE_FACTORY = newFactory(Locale.class, LOCALE);
|
public static final TypeAdapter.Factory LOCALE_FACTORY = newFactory(Locale.class, LOCALE);
|
||||||
|
|
||||||
|
public static final TypeAdapter<JsonElement> JSON_ELEMENT = new TypeAdapter<JsonElement>() {
|
||||||
|
@Override public JsonElement read(JsonReader reader) throws IOException {
|
||||||
|
switch (reader.peek()) {
|
||||||
|
case STRING:
|
||||||
|
return new JsonPrimitive(reader.nextString());
|
||||||
|
case NUMBER:
|
||||||
|
String number = reader.nextString();
|
||||||
|
return new JsonPrimitive(new LazilyParsedNumber(number));
|
||||||
|
case BOOLEAN:
|
||||||
|
return new JsonPrimitive(reader.nextBoolean());
|
||||||
|
case NULL:
|
||||||
|
reader.nextNull();
|
||||||
|
return JsonNull.INSTANCE;
|
||||||
|
case BEGIN_ARRAY:
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
reader.beginArray();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
array.add(read(reader));
|
||||||
|
}
|
||||||
|
reader.endArray();
|
||||||
|
return array;
|
||||||
|
case BEGIN_OBJECT:
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
reader.beginObject();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
object.add(reader.nextName(), read(reader));
|
||||||
|
}
|
||||||
|
reader.endObject();
|
||||||
|
return object;
|
||||||
|
case END_DOCUMENT:
|
||||||
|
case NAME:
|
||||||
|
case END_OBJECT:
|
||||||
|
case END_ARRAY:
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void write(JsonWriter writer, JsonElement value) throws IOException {
|
||||||
|
if (value == null || value.isJsonNull()) {
|
||||||
|
writer.nullValue();
|
||||||
|
} else if (value.isJsonPrimitive()) {
|
||||||
|
JsonPrimitive primitive = value.getAsJsonPrimitive();
|
||||||
|
if (primitive.isNumber()) {
|
||||||
|
writer.value(primitive.getAsNumber());
|
||||||
|
} else if (primitive.isBoolean()) {
|
||||||
|
writer.value(primitive.getAsBoolean());
|
||||||
|
} else {
|
||||||
|
writer.value(primitive.getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (value.isJsonArray()) {
|
||||||
|
writer.beginArray();
|
||||||
|
for (JsonElement e : value.getAsJsonArray()) {
|
||||||
|
write(writer, e);
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
|
||||||
|
} else if (value.isJsonObject()) {
|
||||||
|
writer.beginObject();
|
||||||
|
for (Map.Entry<String, JsonElement> e : value.getAsJsonObject().entrySet()) {
|
||||||
|
writer.name(e.getKey());
|
||||||
|
write(writer, e.getValue());
|
||||||
|
}
|
||||||
|
writer.endObject();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Couldn't write " + value.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final TypeAdapter.Factory JSON_ELEMENT_FACTORY
|
||||||
|
= newFactory(JsonElement.class, JSON_ELEMENT);
|
||||||
|
|
||||||
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
|
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
|
||||||
private final Class<T> classOfT;
|
private final Class<T> classOfT;
|
||||||
|
|
||||||
|
@ -17,10 +17,14 @@ package com.google.gson.functional;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonNull;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@ -459,6 +463,66 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testJsonPrimitiveSerialization() {
|
||||||
|
assertEquals("5", gson.toJson(new JsonPrimitive(5), JsonElement.class));
|
||||||
|
assertEquals("true", gson.toJson(new JsonPrimitive(true), JsonElement.class));
|
||||||
|
assertEquals("\"foo\"", gson.toJson(new JsonPrimitive("foo"), JsonElement.class));
|
||||||
|
assertEquals("\"a\"", gson.toJson(new JsonPrimitive('a'), JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonPrimitiveDeserialization() {
|
||||||
|
assertEquals(new JsonPrimitive(5), gson.fromJson("5", JsonElement.class));
|
||||||
|
assertEquals(new JsonPrimitive(true), gson.fromJson("true", JsonElement.class));
|
||||||
|
assertEquals(new JsonPrimitive("foo"), gson.fromJson("\"foo\"", JsonElement.class));
|
||||||
|
assertEquals(new JsonPrimitive('a'), gson.fromJson("\"a\"", JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonNullSerialization() {
|
||||||
|
assertEquals("null", gson.toJson(JsonNull.INSTANCE, JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNullJsonElementSerialization() {
|
||||||
|
assertEquals("null", gson.toJson(null, JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonArraySerialization() {
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
array.add(new JsonPrimitive(1));
|
||||||
|
array.add(new JsonPrimitive(2));
|
||||||
|
array.add(new JsonPrimitive(3));
|
||||||
|
assertEquals("[1,2,3]", gson.toJson(array, JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonArrayDeerialization() {
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
array.add(new JsonPrimitive(1));
|
||||||
|
array.add(new JsonPrimitive(2));
|
||||||
|
array.add(new JsonPrimitive(3));
|
||||||
|
assertEquals(array, gson.fromJson("[1,2,3]", JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonObjectSerialization() {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.add("foo", new JsonPrimitive(1));
|
||||||
|
object.add("bar", new JsonPrimitive(2));
|
||||||
|
assertEquals("{\"foo\":1,\"bar\":2}", gson.toJson(object, JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonObjectDeerialization() {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.add("foo", new JsonPrimitive(1));
|
||||||
|
object.add("bar", new JsonPrimitive(2));
|
||||||
|
assertEquals(object, gson.fromJson("{\"foo\":1,\"bar\":2}", JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testJsonNullDeerialization() {
|
||||||
|
assertEquals(JsonNull.INSTANCE, gson.fromJson("null", JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNullJsonElementDeserialization() {
|
||||||
|
assertEquals(JsonNull.INSTANCE, gson.fromJson("null", JsonElement.class));
|
||||||
|
}
|
||||||
|
|
||||||
private static class ClassWithBigDecimal {
|
private static class ClassWithBigDecimal {
|
||||||
BigDecimal value;
|
BigDecimal value;
|
||||||
ClassWithBigDecimal(String value) {
|
ClassWithBigDecimal(String value) {
|
||||||
|
Loading…
Reference in New Issue
Block a user