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 java.io.IOException;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
|
import okio.BufferedSource;
|
||||||
import okio.Sink;
|
import okio.Sink;
|
||||||
|
|
||||||
import static com.squareup.moshi.JsonScope.DANGLING_NAME;
|
import static com.squareup.moshi.JsonScope.DANGLING_NAME;
|
||||||
@@ -261,6 +262,18 @@ final class JsonUtf8Writer extends JsonWriter {
|
|||||||
return this;
|
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}
|
* Ensures all buffered data is written to the underlying {@link Sink}
|
||||||
* and flushes that writer.
|
* and flushes that writer.
|
||||||
|
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
|
||||||
import static com.squareup.moshi.JsonScope.EMPTY_ARRAY;
|
import static com.squareup.moshi.JsonScope.EMPTY_ARRAY;
|
||||||
import static com.squareup.moshi.JsonScope.EMPTY_DOCUMENT;
|
import static com.squareup.moshi.JsonScope.EMPTY_DOCUMENT;
|
||||||
@@ -205,6 +206,23 @@ final class JsonValueWriter extends JsonWriter {
|
|||||||
return this;
|
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 {
|
@Override public void close() throws IOException {
|
||||||
int size = stackSize;
|
int size = stackSize;
|
||||||
if (size > 1 || size == 1 && scopes[size - 1] != NONEMPTY_DOCUMENT) {
|
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.CheckReturnValue;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
|
||||||
import static com.squareup.moshi.JsonScope.EMPTY_OBJECT;
|
import static com.squareup.moshi.JsonScope.EMPTY_OBJECT;
|
||||||
import static com.squareup.moshi.JsonScope.NONEMPTY_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;
|
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
|
* 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.
|
||||||
|
@@ -107,4 +107,20 @@ public final class JsonUtf8WriterTest {
|
|||||||
// JsonWriter doesn't attempt to detect duplicate names
|
// JsonWriter doesn't attempt to detect duplicate names
|
||||||
assertThat(buffer.readUtf8()).isEqualTo("{\"a\":1,\"a\":2}");
|
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.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import okio.Buffer;
|
||||||
import org.junit.Test;
|
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.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.entry;
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@@ -239,6 +241,22 @@ public final class JsonValueWriterTest {
|
|||||||
assertThat((List<?>) writer.root()).isEqualTo(numbers);
|
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
|
* 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
|
* 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;
|
package com.squareup.moshi;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import okio.Buffer;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.runners.Parameterized;
|
||||||
@@ -333,4 +334,21 @@ public final class PromoteNameToValueTest {
|
|||||||
}
|
}
|
||||||
writer.name("a");
|
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