mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19:21 +08:00
Merge pull request #503 from square/eric.write-from-source
Allow writing out raw JSON.
This commit is contained in:
@@ -18,6 +18,7 @@ package com.squareup.moshi;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nullable;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Sink;
|
||||
|
||||
import static com.squareup.moshi.JsonScope.DANGLING_NAME;
|
||||
@@ -261,6 +262,18 @@ final class JsonUtf8Writer extends JsonWriter {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public JsonWriter value(BufferedSource source) throws IOException {
|
||||
if (promoteValueToName) {
|
||||
throw new IllegalStateException(
|
||||
"BufferedSource cannot be used as a map key in JSON at path " + getPath());
|
||||
}
|
||||
writeDeferredName();
|
||||
beforeValue();
|
||||
sink.writeAll(source);
|
||||
pathIndices[stackSize - 1]++;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures all buffered data is written to the underlying {@link Sink}
|
||||
* and flushes that writer.
|
||||
|
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import okio.BufferedSource;
|
||||
|
||||
import static com.squareup.moshi.JsonScope.EMPTY_ARRAY;
|
||||
import static com.squareup.moshi.JsonScope.EMPTY_DOCUMENT;
|
||||
@@ -205,6 +206,23 @@ final class JsonValueWriter extends JsonWriter {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public JsonWriter value(BufferedSource source) throws IOException {
|
||||
if (promoteValueToName) {
|
||||
throw new IllegalStateException(
|
||||
"BufferedSource cannot be used as a map key in JSON at path " + getPath());
|
||||
}
|
||||
Object value = JsonReader.of(source).readJsonValue();
|
||||
boolean serializeNulls = this.serializeNulls;
|
||||
this.serializeNulls = true;
|
||||
try {
|
||||
add(value);
|
||||
} finally {
|
||||
this.serializeNulls = serializeNulls;
|
||||
}
|
||||
pathIndices[stackSize - 1]++;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public void close() throws IOException {
|
||||
int size = stackSize;
|
||||
if (size > 1 || size == 1 && scopes[size - 1] != NONEMPTY_DOCUMENT) {
|
||||
|
@@ -22,6 +22,7 @@ import java.util.Arrays;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
import javax.annotation.Nullable;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
|
||||
import static com.squareup.moshi.JsonScope.EMPTY_OBJECT;
|
||||
import static com.squareup.moshi.JsonScope.NONEMPTY_OBJECT;
|
||||
@@ -335,6 +336,15 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
||||
*/
|
||||
public abstract JsonWriter value(@Nullable Number value) throws IOException;
|
||||
|
||||
/**
|
||||
* Writes {@code source} directly without encoding its contents.
|
||||
* Since no validation is performed, {@link #setSerializeNulls} and other writer configurations
|
||||
* are not respected.
|
||||
*
|
||||
* @return this writer.
|
||||
*/
|
||||
public abstract JsonWriter value(BufferedSource source) throws IOException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@@ -107,4 +107,20 @@ public final class JsonUtf8WriterTest {
|
||||
// JsonWriter doesn't attempt to detect duplicate names
|
||||
assertThat(buffer.readUtf8()).isEqualTo("{\"a\":1,\"a\":2}");
|
||||
}
|
||||
|
||||
@Test public void valueFromSource() throws IOException {
|
||||
Buffer buffer = new Buffer();
|
||||
JsonWriter writer = JsonUtf8Writer.of(buffer);
|
||||
writer.beginObject();
|
||||
writer.name("a");
|
||||
writer.value(new Buffer().writeUtf8("[\"value\"]"));
|
||||
writer.name("b");
|
||||
writer.value(new Buffer().writeUtf8("2"));
|
||||
writer.name("c");
|
||||
writer.value(3);
|
||||
writer.name("d");
|
||||
writer.value(new Buffer().writeUtf8("null"));
|
||||
writer.endObject();
|
||||
assertThat(buffer.readUtf8()).isEqualTo("{\"a\":[\"value\"],\"b\":2,\"c\":3,\"d\":null}");
|
||||
}
|
||||
}
|
||||
|
@@ -23,8 +23,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import okio.Buffer;
|
||||
import org.junit.Test;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -239,6 +241,22 @@ public final class JsonValueWriterTest {
|
||||
assertThat((List<?>) writer.root()).isEqualTo(numbers);
|
||||
}
|
||||
|
||||
@Test public void valueFromSource() throws IOException {
|
||||
JsonValueWriter writer = new JsonValueWriter();
|
||||
writer.beginObject();
|
||||
writer.name("a");
|
||||
writer.value(new Buffer().writeUtf8("[\"value\"]"));
|
||||
writer.name("b");
|
||||
writer.value(new Buffer().writeUtf8("2"));
|
||||
writer.name("c");
|
||||
writer.value(3);
|
||||
writer.name("d");
|
||||
writer.value(new Buffer().writeUtf8("null"));
|
||||
writer.endObject();
|
||||
assertThat((Map<?, ?>) writer.root()).containsExactly(
|
||||
entry("a", singletonList("value")), entry("b", 2.0d), entry("c", 3L), entry("d", null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of number whose {@link #toString} is {@code s}. Using the standard number
|
||||
* methods like {@link Number#doubleValue} are awkward because they may truncate or discard
|
||||
@@ -268,4 +286,3 @@ public final class JsonValueWriterTest {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
package com.squareup.moshi;
|
||||
|
||||
import java.util.List;
|
||||
import okio.Buffer;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
@@ -333,4 +334,21 @@ public final class PromoteNameToValueTest {
|
||||
}
|
||||
writer.name("a");
|
||||
}
|
||||
|
||||
@Test public void writerSourceValueFails() throws Exception {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
try {
|
||||
writer.value(new Buffer().writeUtf8("\"a\""));
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
assertThat(expected).hasMessage(
|
||||
"BufferedSource cannot be used as a map key in JSON at path $.");
|
||||
}
|
||||
writer.value("a");
|
||||
writer.value("a value");
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{\"a\":\"a value\"}");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user