mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 07:59:21 +08:00
Merge pull request #1098 from square/jakew/json-value-writer/2020-02-14
Add JsonWriter.jsonValue API
This commit is contained in:
@@ -429,6 +429,7 @@ public abstract class JsonReader implements Closeable {
|
||||
*
|
||||
* @throws JsonDataException if the next token is not a literal value, if a JSON object has a
|
||||
* duplicate key.
|
||||
* @see JsonWriter#jsonValue(Object)
|
||||
*/
|
||||
public final @Nullable Object readJsonValue() throws IOException {
|
||||
switch (peek()) {
|
||||
|
@@ -19,6 +19,8 @@ import java.io.Closeable;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
import javax.annotation.Nullable;
|
||||
import okio.BufferedSink;
|
||||
@@ -386,6 +388,58 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
||||
@CheckReturnValue
|
||||
public abstract BufferedSink valueSink() throws IOException;
|
||||
|
||||
/**
|
||||
* Encodes the value which may be a string, number, boolean, null, map, or list.
|
||||
*
|
||||
* @return this writer.
|
||||
* @see JsonReader#readJsonValue()
|
||||
*/
|
||||
public final JsonWriter jsonValue(@Nullable Object value) throws IOException {
|
||||
if (value instanceof Map<?, ?>) {
|
||||
beginObject();
|
||||
for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
if (!(key instanceof String)) {
|
||||
throw new IllegalArgumentException(key == null
|
||||
? "Map keys must be non-null"
|
||||
: "Map keys must be of type String: " + key.getClass().getName());
|
||||
}
|
||||
name(((String) key));
|
||||
jsonValue(entry.getValue());
|
||||
}
|
||||
endObject();
|
||||
|
||||
} else if (value instanceof List<?>) {
|
||||
beginArray();
|
||||
for (Object element : ((List<?>) value)) {
|
||||
jsonValue(element);
|
||||
}
|
||||
endArray();
|
||||
|
||||
} else if (value instanceof String) {
|
||||
value(((String) value));
|
||||
|
||||
} else if (value instanceof Boolean) {
|
||||
value(((Boolean) value).booleanValue());
|
||||
|
||||
} else if (value instanceof Double) {
|
||||
value(((Double) value).doubleValue());
|
||||
|
||||
} else if (value instanceof Long) {
|
||||
value(((Long) value).longValue());
|
||||
|
||||
} else if (value instanceof Number) {
|
||||
value(((Number) value));
|
||||
|
||||
} else if (value == null) {
|
||||
nullValue();
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported type: " + value.getClass().getName());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the writer to treat the next value as a string name. This is useful for map adapters so
|
||||
* that arbitrary type adapters can use {@link #value} to write a name value.
|
||||
|
@@ -18,7 +18,11 @@ package com.squareup.moshi;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import okio.BufferedSink;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -742,4 +746,72 @@ public final class JsonWriterTest {
|
||||
assertThat(factory.json()).isEqualTo("{\"a\":1.0}");
|
||||
sink.close();
|
||||
}
|
||||
|
||||
@Test public void jsonValueTypes() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.setSerializeNulls(true);
|
||||
|
||||
writer.beginArray();
|
||||
writer.jsonValue(null);
|
||||
writer.jsonValue(1.1d);
|
||||
writer.jsonValue(1L);
|
||||
writer.jsonValue(1);
|
||||
writer.jsonValue(true);
|
||||
writer.jsonValue("one");
|
||||
writer.jsonValue(Collections.emptyList());
|
||||
writer.jsonValue(Arrays.asList(1, 2, null, 3));
|
||||
writer.jsonValue(Collections.emptyMap());
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("one", "uno");
|
||||
map.put("two", null);
|
||||
writer.jsonValue(map);
|
||||
writer.endArray();
|
||||
|
||||
assertThat(factory.json()).isEqualTo("["
|
||||
+ "null,"
|
||||
+ "1.1,"
|
||||
+ "1,"
|
||||
+ "1,"
|
||||
+ "true,"
|
||||
+ "\"one\","
|
||||
+ "[],"
|
||||
+ "[1,2,null,3],"
|
||||
+ "{},"
|
||||
+ "{\"one\":\"uno\",\"two\":null}"
|
||||
+ "]");
|
||||
}
|
||||
|
||||
@Test public void jsonValueIllegalTypes() throws IOException {
|
||||
try {
|
||||
factory.newWriter().jsonValue(new Object());
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e).hasMessage("Unsupported type: java.lang.Object");
|
||||
}
|
||||
|
||||
try {
|
||||
factory.newWriter().jsonValue('1');
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e).hasMessage("Unsupported type: java.lang.Character");
|
||||
}
|
||||
|
||||
Map<Integer, String> mapWrongKey = new LinkedHashMap<>();
|
||||
mapWrongKey.put(1, "one");
|
||||
try {
|
||||
factory.newWriter().jsonValue(mapWrongKey);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e).hasMessage("Map keys must be of type String: java.lang.Integer");
|
||||
}
|
||||
|
||||
Map<String, String> mapNullKey = new LinkedHashMap<>();
|
||||
mapNullKey.put(null, "one");
|
||||
try {
|
||||
factory.newWriter().jsonValue(mapNullKey);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e).hasMessage("Map keys must be non-null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user