mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19:21 +08:00
Add JsonWriter.jsonValue API
This is symmetric with JsonReader.readJsonValue in that it writes an Object comprised of maps, lists, and some scalars.
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
|
* @throws JsonDataException if the next token is not a literal value, if a JSON object has a
|
||||||
* duplicate key.
|
* duplicate key.
|
||||||
|
* @see JsonWriter#jsonValue(Object)
|
||||||
*/
|
*/
|
||||||
public final @Nullable Object readJsonValue() throws IOException {
|
public final @Nullable Object readJsonValue() throws IOException {
|
||||||
switch (peek()) {
|
switch (peek()) {
|
||||||
|
@@ -19,6 +19,8 @@ import java.io.Closeable;
|
|||||||
import java.io.Flushable;
|
import java.io.Flushable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.annotation.CheckReturnValue;
|
import javax.annotation.CheckReturnValue;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
@@ -386,6 +388,58 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
|||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
public abstract BufferedSink valueSink() throws IOException;
|
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
|
* 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.
|
* 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.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -742,4 +746,72 @@ public final class JsonWriterTest {
|
|||||||
assertThat(factory.json()).isEqualTo("{\"a\":1.0}");
|
assertThat(factory.json()).isEqualTo("{\"a\":1.0}");
|
||||||
sink.close();
|
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