Add JsonReader.readJsonValue

This commit is contained in:
Eric Cochran
2017-02-03 14:47:34 -08:00
parent 7013651dd5
commit 332adcadf5
3 changed files with 88 additions and 44 deletions

View File

@@ -17,6 +17,9 @@ package com.squareup.moshi;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import okio.Buffer;
import okio.BufferedSource;
import okio.ByteString;
@@ -390,6 +393,57 @@ public abstract class JsonReader implements Closeable {
*/
public abstract void skipValue() throws IOException;
/**
* Returns the value of the next token, consuming it. The result may be a string, number, boolean,
* null, map, or list, according to the JSON structure.
*
* @throws JsonDataException if the next token is not a literal value, if a JSON object has a
* duplicate key.
*/
public final Object readJsonValue() throws IOException {
switch (peek()) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<>();
beginArray();
while (hasNext()) {
list.add(readJsonValue());
}
endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedHashTreeMap<>();
beginObject();
while (hasNext()) {
String name = nextName();
Object value = readJsonValue();
Object replaced = map.put(name, value);
if (replaced != null) {
throw new JsonDataException("Map key '" + name + "' has multiple values at path "
+ getPath() + ": " + replaced + " and " + value);
}
}
endObject();
return map;
case STRING:
return nextString();
case NUMBER:
return nextDouble();
case BOOLEAN:
return nextBoolean();
case NULL:
return nextNull();
default:
throw new IllegalStateException(
"Expected a value but was " + peek() + " at path " + getPath());
}
}
/**
* Returns a <a href="http://goessner.net/articles/JsonPath/">JsonPath</a> to
* the current location in the JSON value.

View File

@@ -18,11 +18,8 @@ package com.squareup.moshi;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -272,47 +269,7 @@ final class StandardJsonAdapters {
}
@Override public Object fromJson(JsonReader reader) throws IOException {
switch (reader.peek()) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
list.add(fromJson(reader));
}
reader.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedHashTreeMap<>();
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
Object value = fromJson(reader);
Object replaced = map.put(name, value);
if (replaced != null) {
throw new JsonDataException("Map key '" + name + "' has multiple values at path "
+ reader.getPath() + ": " + replaced + " and " + value);
}
}
reader.endObject();
return map;
case STRING:
return reader.nextString();
case NUMBER:
return reader.nextDouble();
case BOOLEAN:
return reader.nextBoolean();
case NULL:
return reader.nextNull();
default:
throw new IllegalStateException("Expected a value but was " + reader.peek()
+ " at path " + reader.getPath());
}
return reader.readJsonValue();
}
@Override public void toJson(JsonWriter writer, Object value) throws IOException {

View File

@@ -17,6 +17,8 @@ package com.squareup.moshi;
import java.io.EOFException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -912,4 +914,35 @@ public final class JsonReaderTest {
assertThat(reader.nextString()).isEqualTo("a");
reader.endArray();
}
@Test public void readJsonValueInt() throws IOException {
JsonReader reader = newReader("1");
Object value = reader.readJsonValue();
assertThat(value).isEqualTo(1.0);
}
@Test public void readJsonValueMap() throws IOException {
JsonReader reader = newReader("{\"hello\": \"world\"}");
Object value = reader.readJsonValue();
assertThat(value).isEqualTo(Collections.singletonMap("hello", "world"));
}
@Test public void readJsonValueList() throws IOException {
JsonReader reader = newReader("[\"a\", \"b\"]");
Object value = reader.readJsonValue();
assertThat(value).isEqualTo(Arrays.asList("a", "b"));
}
@Test public void readJsonValueListMultipleTypes() throws IOException {
JsonReader reader = newReader("[\"a\", 5, false]");
Object value = reader.readJsonValue();
assertThat(value).isEqualTo(Arrays.asList("a", 5.0, false));
}
@Test public void readJsonValueNestedListInMap() throws IOException {
JsonReader reader = newReader("{\"pizzas\": [\"cheese\", \"pepperoni\"]}");
Object value = reader.readJsonValue();
assertThat(value).isEqualTo(
Collections.singletonMap("pizzas", Arrays.asList("cheese", "pepperoni")));
}
}