-
Couldn't load subscription status.
- Fork 4.4k
Make Object and JsonElement deserialization iterative
#1912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
539952e
e35f674
dce0d06
e1f5a59
f7d3c18
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ | |
| import java.util.Currency; | ||
| import java.util.GregorianCalendar; | ||
| import java.util.HashMap; | ||
| import java.util.LinkedList; | ||
| import java.util.List; | ||
| import java.util.Locale; | ||
| import java.util.Map; | ||
|
|
@@ -695,12 +696,25 @@ public void write(JsonWriter out, Locale value) throws IOException { | |
| public static final TypeAdapterFactory LOCALE_FACTORY = newFactory(Locale.class, LOCALE); | ||
|
|
||
| public static final TypeAdapter<JsonElement> JSON_ELEMENT = new TypeAdapter<JsonElement>() { | ||
| @Override public JsonElement read(JsonReader in) throws IOException { | ||
| if (in instanceof JsonTreeReader) { | ||
| return ((JsonTreeReader) in).nextJsonElement(); | ||
| /** | ||
| * Tries to begin reading a JSON array or JSON object, returning {@code null} if | ||
| * the next element is neither of those. | ||
| */ | ||
| private JsonElement tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { | ||
| if (peeked == JsonToken.BEGIN_ARRAY) { | ||
|
||
| in.beginArray(); | ||
| return new JsonArray(); | ||
| } else if (peeked == JsonToken.BEGIN_OBJECT) { | ||
| in.beginObject(); | ||
| return new JsonObject(); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| switch (in.peek()) { | ||
| /** Reads a {@link JsonElement} which cannot have any nested elements */ | ||
| private JsonElement readTerminal(JsonReader in, JsonToken peeked) throws IOException { | ||
| switch (peeked) { | ||
| case STRING: | ||
| return new JsonPrimitive(in.nextString()); | ||
| case NUMBER: | ||
|
|
@@ -711,28 +725,69 @@ public void write(JsonWriter out, Locale value) throws IOException { | |
| case NULL: | ||
| in.nextNull(); | ||
| return JsonNull.INSTANCE; | ||
| case BEGIN_ARRAY: | ||
| JsonArray array = new JsonArray(); | ||
| in.beginArray(); | ||
| default: | ||
| // When read(JsonReader) is called with JsonReader in invalid state | ||
| throw new IllegalStateException("Unexpected token: " + peeked); | ||
| } | ||
| } | ||
|
|
||
| @Override public JsonElement read(JsonReader in) throws IOException { | ||
| if (in instanceof JsonTreeReader) { | ||
| return ((JsonTreeReader) in).nextJsonElement(); | ||
| } | ||
|
|
||
| // Either JsonArray or JsonObject | ||
| JsonElement current; | ||
| JsonToken peeked = in.peek(); | ||
|
|
||
| current = tryBeginNesting(in, peeked); | ||
| if (current == null) { | ||
| return readTerminal(in, peeked); | ||
| } | ||
|
|
||
| LinkedList<JsonElement> stack = new LinkedList<>(); | ||
|
|
||
| while (true) { | ||
| while (in.hasNext()) { | ||
| array.add(read(in)); | ||
| String name = null; | ||
| // Name is only used for JSON object members | ||
| if (current instanceof JsonObject) { | ||
| name = in.nextName(); | ||
| } | ||
|
|
||
| peeked = in.peek(); | ||
| JsonElement value = tryBeginNesting(in, peeked); | ||
| boolean isNesting = value != null; | ||
|
|
||
| if (value == null) { | ||
| value = readTerminal(in, peeked); | ||
| } | ||
|
|
||
| if (current instanceof JsonArray) { | ||
| ((JsonArray) current).add(value); | ||
| } else { | ||
| ((JsonObject) current).add(name, value); | ||
| } | ||
|
|
||
| if (isNesting) { | ||
| stack.addLast(current); | ||
| current = value; | ||
| } | ||
| } | ||
| in.endArray(); | ||
| return array; | ||
| case BEGIN_OBJECT: | ||
| JsonObject object = new JsonObject(); | ||
| in.beginObject(); | ||
| while (in.hasNext()) { | ||
| object.add(in.nextName(), read(in)); | ||
|
|
||
| // End current element | ||
| if (current instanceof JsonArray) { | ||
| in.endArray(); | ||
| } else { | ||
| in.endObject(); | ||
| } | ||
|
|
||
| if (stack.isEmpty()) { | ||
| return current; | ||
| } else { | ||
| // Continue with enclosing element | ||
| current = stack.removeLast(); | ||
| } | ||
| in.endObject(); | ||
| return object; | ||
| case END_DOCUMENT: | ||
| case NAME: | ||
| case END_OBJECT: | ||
| case END_ARRAY: | ||
| default: | ||
| throw new IllegalArgumentException(); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package com.google.gson; | ||
|
|
||
| import static org.junit.Assert.assertEquals; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Arrays; | ||
| import org.junit.Test; | ||
| import org.junit.runner.RunWith; | ||
| import org.junit.runners.Parameterized; | ||
| import org.junit.runners.Parameterized.Parameter; | ||
| import org.junit.runners.Parameterized.Parameters; | ||
|
|
||
| @RunWith(Parameterized.class) | ||
| public class JsonParserParameterizedTest { | ||
| @Parameters | ||
| public static Iterable<String> data() { | ||
| return Arrays.asList( | ||
| "[]", | ||
| "{}", | ||
| "null", | ||
| "1.0", | ||
| "true", | ||
| "\"string\"", | ||
| "[true,1.0,null,{},2.0,{\"a\":[false]},[3.0,\"test\"],4.0]", | ||
| "{\"\":1.0,\"a\":true,\"b\":null,\"c\":[],\"d\":{\"a1\":2.0,\"b2\":[true,{\"a3\":3.0}]},\"e\":[{\"f\":4.0},\"test\"]}" | ||
| ); | ||
| } | ||
|
|
||
| private final TypeAdapter<JsonElement> adapter = new Gson().getAdapter(JsonElement.class); | ||
| @Parameter | ||
| public String json; | ||
|
|
||
| @Test | ||
| public void testParse() throws IOException { | ||
| JsonElement deserialized = JsonParser.parseString(json); | ||
| String actualSerialized = adapter.toJson(deserialized); | ||
|
|
||
| // Serialized JsonElement should be the same as original JSON | ||
| assertEquals(json, actualSerialized); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.