mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19:21 +08:00
@@ -188,7 +188,7 @@ final class BufferedSinkJsonWriter extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value on the top of the stack.
|
* Returns the scope on the top of the stack.
|
||||||
*/
|
*/
|
||||||
private int peek() {
|
private int peek() {
|
||||||
if (stackSize == 0) {
|
if (stackSize == 0) {
|
||||||
@@ -212,7 +212,7 @@ final class BufferedSinkJsonWriter extends JsonWriter {
|
|||||||
throw new IllegalStateException("JsonWriter is closed.");
|
throw new IllegalStateException("JsonWriter is closed.");
|
||||||
}
|
}
|
||||||
if (deferredName != null) {
|
if (deferredName != null) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException("Nesting problem.");
|
||||||
}
|
}
|
||||||
deferredName = name;
|
deferredName = name;
|
||||||
pathNames[stackSize - 1] = name;
|
pathNames[stackSize - 1] = name;
|
||||||
|
@@ -69,7 +69,7 @@ final class MapJsonAdapter<K, V> extends JsonAdapter<Map<K, V>> {
|
|||||||
V replaced = result.put(name, value);
|
V replaced = result.put(name, value);
|
||||||
if (replaced != null) {
|
if (replaced != null) {
|
||||||
throw new JsonDataException("Map key '" + name + "' has multiple values at path "
|
throw new JsonDataException("Map key '" + name + "' has multiple values at path "
|
||||||
+ reader.getPath());
|
+ reader.getPath() + ": " + replaced + " and " + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
237
moshi/src/main/java/com/squareup/moshi/ObjectJsonWriter.java
Normal file
237
moshi/src/main/java/com/squareup/moshi/ObjectJsonWriter.java
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Square, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.squareup.moshi;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.squareup.moshi.JsonScope.EMPTY_ARRAY;
|
||||||
|
import static com.squareup.moshi.JsonScope.EMPTY_DOCUMENT;
|
||||||
|
import static com.squareup.moshi.JsonScope.EMPTY_OBJECT;
|
||||||
|
import static com.squareup.moshi.JsonScope.NONEMPTY_DOCUMENT;
|
||||||
|
|
||||||
|
/** Writes JSON by building a Java object comprising maps, lists, and JSON primitives. */
|
||||||
|
final class ObjectJsonWriter extends JsonWriter {
|
||||||
|
private String indent;
|
||||||
|
private boolean lenient;
|
||||||
|
private boolean serializeNulls;
|
||||||
|
|
||||||
|
private final Object[] stack = new Object[32];
|
||||||
|
private final int[] scopes = new int[32];
|
||||||
|
private final String[] pathNames = new String[32];
|
||||||
|
private final int[] pathIndices = new int[32];
|
||||||
|
private int stackSize = 0;
|
||||||
|
private String deferredName;
|
||||||
|
|
||||||
|
ObjectJsonWriter() {
|
||||||
|
scopes[stackSize++] = EMPTY_DOCUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object root() {
|
||||||
|
int size = stackSize;
|
||||||
|
if (size > 1 || size == 1 && scopes[size - 1] != NONEMPTY_DOCUMENT) {
|
||||||
|
throw new IllegalStateException("Incomplete document");
|
||||||
|
}
|
||||||
|
return stack[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setIndent(String indent) {
|
||||||
|
this.indent = indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String getIndent() {
|
||||||
|
return indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setLenient(boolean lenient) {
|
||||||
|
this.lenient = lenient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean isLenient() {
|
||||||
|
return lenient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setSerializeNulls(boolean serializeNulls) {
|
||||||
|
this.serializeNulls = serializeNulls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean getSerializeNulls() {
|
||||||
|
return serializeNulls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter beginArray() throws IOException {
|
||||||
|
if (stackSize == stack.length) {
|
||||||
|
throw new JsonDataException("Nesting too deep at " + getPath() + ": circular reference?");
|
||||||
|
}
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
add(list);
|
||||||
|
stack[stackSize] = list;
|
||||||
|
scopes[stackSize] = EMPTY_ARRAY;
|
||||||
|
pathIndices[stackSize] = 0;
|
||||||
|
stackSize++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter endArray() throws IOException {
|
||||||
|
if (peek() != EMPTY_ARRAY) {
|
||||||
|
throw new IllegalStateException("Nesting problem.");
|
||||||
|
}
|
||||||
|
stackSize--;
|
||||||
|
stack[stackSize] = null;
|
||||||
|
pathIndices[stackSize - 1]++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter beginObject() throws IOException {
|
||||||
|
if (stackSize == stack.length) {
|
||||||
|
throw new JsonDataException("Nesting too deep at " + getPath() + ": circular reference?");
|
||||||
|
}
|
||||||
|
Map<String, Object> map = new LinkedHashTreeMap<>();
|
||||||
|
add(map);
|
||||||
|
stack[stackSize] = map;
|
||||||
|
scopes[stackSize] = EMPTY_OBJECT;
|
||||||
|
stackSize++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter endObject() throws IOException {
|
||||||
|
if (peek() != EMPTY_OBJECT || deferredName != null) {
|
||||||
|
throw new IllegalStateException("Nesting problem.");
|
||||||
|
}
|
||||||
|
stackSize--;
|
||||||
|
stack[stackSize] = null;
|
||||||
|
pathNames[stackSize] = null; // Free the last path name so that it can be garbage collected!
|
||||||
|
pathIndices[stackSize - 1]++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter name(String name) throws IOException {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name == null");
|
||||||
|
}
|
||||||
|
if (stackSize == 0) {
|
||||||
|
throw new IllegalStateException("JsonWriter is closed.");
|
||||||
|
}
|
||||||
|
if (peek() != EMPTY_OBJECT || deferredName != null) {
|
||||||
|
throw new IllegalStateException("Nesting problem.");
|
||||||
|
}
|
||||||
|
pathNames[stackSize - 1] = name;
|
||||||
|
deferredName = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter value(String value) throws IOException {
|
||||||
|
return add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter nullValue() throws IOException {
|
||||||
|
return add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter value(boolean value) throws IOException {
|
||||||
|
return add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter value(Boolean value) throws IOException {
|
||||||
|
return add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter value(double value) throws IOException {
|
||||||
|
return value(Double.valueOf(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter value(long value) throws IOException {
|
||||||
|
return add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public JsonWriter value(Number value) throws IOException {
|
||||||
|
if (!lenient) {
|
||||||
|
double d = value.doubleValue();
|
||||||
|
if (d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY || Double.isNaN(d)) {
|
||||||
|
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override void promoteNameToValue() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String getPath() {
|
||||||
|
return JsonScope.getPath(stackSize, scopes, pathNames, pathIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void close() throws IOException {
|
||||||
|
int size = stackSize;
|
||||||
|
if (size > 1 || size == 1 && scopes[size - 1] != NONEMPTY_DOCUMENT) {
|
||||||
|
throw new IOException("Incomplete document");
|
||||||
|
}
|
||||||
|
stackSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void flush() throws IOException {
|
||||||
|
if (stackSize == 0) {
|
||||||
|
throw new IllegalStateException("JsonWriter is closed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the scope on the top of the stack.
|
||||||
|
*/
|
||||||
|
private int peek() {
|
||||||
|
if (stackSize == 0) {
|
||||||
|
throw new IllegalStateException("JsonWriter is closed.");
|
||||||
|
}
|
||||||
|
return scopes[stackSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectJsonWriter add(Object newTop) {
|
||||||
|
int scope = peek();
|
||||||
|
|
||||||
|
if (stackSize == 1) {
|
||||||
|
if (scope != EMPTY_DOCUMENT) {
|
||||||
|
throw new IllegalStateException("JSON must have only one top-level value.");
|
||||||
|
}
|
||||||
|
scopes[stackSize - 1] = NONEMPTY_DOCUMENT;
|
||||||
|
stack[stackSize - 1] = newTop;
|
||||||
|
|
||||||
|
} else if (scope == EMPTY_OBJECT && deferredName != null) {
|
||||||
|
if (newTop != null || serializeNulls) {
|
||||||
|
@SuppressWarnings("unchecked") // Our maps always have string keys and object values.
|
||||||
|
Map<String, Object> map = (Map<String, Object>) stack[stackSize - 1];
|
||||||
|
Object replaced = map.put(deferredName, newTop);
|
||||||
|
if (replaced != null) {
|
||||||
|
throw new IllegalArgumentException("Map key '" + deferredName
|
||||||
|
+ "' has multiple values at path " + getPath() + ": " + replaced + " and " + newTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deferredName = null;
|
||||||
|
|
||||||
|
} else if (scope == EMPTY_ARRAY) {
|
||||||
|
@SuppressWarnings("unchecked") // Our lists always have object values.
|
||||||
|
List<Object> list = (List<Object>) stack[stackSize - 1];
|
||||||
|
list.add(newTop);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Nesting problem.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@@ -286,7 +286,13 @@ final class StandardJsonAdapters {
|
|||||||
Map<String, Object> map = new LinkedHashTreeMap<>();
|
Map<String, Object> map = new LinkedHashTreeMap<>();
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
map.put(reader.nextName(), fromJson(reader));
|
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();
|
reader.endObject();
|
||||||
return map;
|
return map;
|
||||||
|
@@ -16,468 +16,15 @@
|
|||||||
package com.squareup.moshi;
|
package com.squareup.moshi;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import okio.Buffer;
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.List;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.junit.runners.Parameterized.Parameter;
|
|
||||||
import org.junit.runners.Parameterized.Parameters;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public final class BufferedSinkJsonWriterTest {
|
public final class BufferedSinkJsonWriterTest {
|
||||||
@Parameter public JsonWriterFactory factory;
|
|
||||||
|
|
||||||
@Parameters(name = "{0}")
|
|
||||||
public static List<Object[]> parameters() {
|
|
||||||
return JsonWriterFactory.factories();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nullsValuesNotSerializedByDefault() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
writer.nullValue();
|
|
||||||
writer.endObject();
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("{}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nullsValuesSerializedWhenConfigured() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.setSerializeNulls(true);
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
writer.nullValue();
|
|
||||||
writer.endObject();
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("{\"a\":null}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void topLevelBoolean() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.value(true);
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("true");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void topLevelNull() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.nullValue();
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("null");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void topLevelInt() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.value(123);
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("123");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void topLevelDouble() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.value(123.4);
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("123.4");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void topLevelString() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.value("a");
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("\"a\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void invalidTopLevelTypes() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.name("hello");
|
|
||||||
try {
|
|
||||||
writer.value("world");
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void twoNames() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
try {
|
|
||||||
writer.name("a");
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nameWithoutValue() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
try {
|
|
||||||
writer.endObject();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void valueWithoutName() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
try {
|
|
||||||
writer.value(true);
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void multipleTopLevelValues() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray().endArray();
|
|
||||||
try {
|
|
||||||
writer.beginArray();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void badNestingObject() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.beginObject();
|
|
||||||
try {
|
|
||||||
writer.endArray();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void badNestingArray() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.beginArray();
|
|
||||||
try {
|
|
||||||
writer.endObject();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nullName() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
try {
|
|
||||||
writer.name(null);
|
|
||||||
fail();
|
|
||||||
} catch (NullPointerException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nullStringValue() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.setSerializeNulls(true);
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
writer.value((String) null);
|
|
||||||
writer.endObject();
|
|
||||||
assertThat(factory.json()).isEqualTo("{\"a\":null}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nonFiniteDoubles() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
try {
|
|
||||||
writer.value(Double.NaN);
|
|
||||||
fail();
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.value(Double.NEGATIVE_INFINITY);
|
|
||||||
fail();
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.value(Double.POSITIVE_INFINITY);
|
|
||||||
fail();
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nonFiniteBoxedDoubles() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
try {
|
|
||||||
writer.value(new Double(Double.NaN));
|
|
||||||
fail();
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.value(new Double(Double.NEGATIVE_INFINITY));
|
|
||||||
fail();
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.value(new Double(Double.POSITIVE_INFINITY));
|
|
||||||
fail();
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void doubles() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value(-0.0);
|
|
||||||
writer.value(1.0);
|
|
||||||
writer.value(Double.MAX_VALUE);
|
|
||||||
writer.value(Double.MIN_VALUE);
|
|
||||||
writer.value(0.0);
|
|
||||||
writer.value(-0.5);
|
|
||||||
writer.value(2.2250738585072014E-308);
|
|
||||||
writer.value(Math.PI);
|
|
||||||
writer.value(Math.E);
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("[-0.0,"
|
|
||||||
+ "1.0,"
|
|
||||||
+ "1.7976931348623157E308,"
|
|
||||||
+ "4.9E-324,"
|
|
||||||
+ "0.0,"
|
|
||||||
+ "-0.5,"
|
|
||||||
+ "2.2250738585072014E-308,"
|
|
||||||
+ "3.141592653589793,"
|
|
||||||
+ "2.718281828459045]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void longs() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value(0);
|
|
||||||
writer.value(1);
|
|
||||||
writer.value(-1);
|
|
||||||
writer.value(Long.MIN_VALUE);
|
|
||||||
writer.value(Long.MAX_VALUE);
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("[0,"
|
|
||||||
+ "1,"
|
|
||||||
+ "-1,"
|
|
||||||
+ "-9223372036854775808,"
|
|
||||||
+ "9223372036854775807]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void numbers() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value(new BigInteger("0"));
|
|
||||||
writer.value(new BigInteger("9223372036854775808"));
|
|
||||||
writer.value(new BigInteger("-9223372036854775809"));
|
|
||||||
writer.value(new BigDecimal("3.141592653589793238462643383"));
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
assertThat(factory.json()).isEqualTo("[0,"
|
|
||||||
+ "9223372036854775808,"
|
|
||||||
+ "-9223372036854775809,"
|
|
||||||
+ "3.141592653589793238462643383]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void booleans() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value(true);
|
|
||||||
writer.value(false);
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[true,false]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void boxedBooleans() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value((Boolean) true);
|
|
||||||
writer.value((Boolean) false);
|
|
||||||
writer.value((Boolean) null);
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[true,false,null]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void nulls() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.nullValue();
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[null]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void strings() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value("a");
|
|
||||||
writer.value("a\"");
|
|
||||||
writer.value("\"");
|
|
||||||
writer.value(":");
|
|
||||||
writer.value(",");
|
|
||||||
writer.value("\b");
|
|
||||||
writer.value("\f");
|
|
||||||
writer.value("\n");
|
|
||||||
writer.value("\r");
|
|
||||||
writer.value("\t");
|
|
||||||
writer.value(" ");
|
|
||||||
writer.value("\\");
|
|
||||||
writer.value("{");
|
|
||||||
writer.value("}");
|
|
||||||
writer.value("[");
|
|
||||||
writer.value("]");
|
|
||||||
writer.value("\0");
|
|
||||||
writer.value("\u0019");
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[\"a\","
|
|
||||||
+ "\"a\\\"\","
|
|
||||||
+ "\"\\\"\","
|
|
||||||
+ "\":\","
|
|
||||||
+ "\",\","
|
|
||||||
+ "\"\\b\","
|
|
||||||
+ "\"\\f\","
|
|
||||||
+ "\"\\n\","
|
|
||||||
+ "\"\\r\","
|
|
||||||
+ "\"\\t\","
|
|
||||||
+ "\" \","
|
|
||||||
+ "\"\\\\\","
|
|
||||||
+ "\"{\","
|
|
||||||
+ "\"}\","
|
|
||||||
+ "\"[\","
|
|
||||||
+ "\"]\","
|
|
||||||
+ "\"\\u0000\","
|
|
||||||
+ "\"\\u0019\"]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void unicodeLineBreaksEscaped() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value("\u2028 \u2029");
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[\"\\u2028 \\u2029\"]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void emptyArray() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void emptyObject() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.endObject();
|
|
||||||
assertThat(factory.json()).isEqualTo("{}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void objectsInArrays() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a").value(5);
|
|
||||||
writer.name("b").value(false);
|
|
||||||
writer.endObject();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("c").value(6);
|
|
||||||
writer.name("d").value(true);
|
|
||||||
writer.endObject();
|
|
||||||
writer.endArray();
|
|
||||||
assertThat(factory.json()).isEqualTo("[{\"a\":5,\"b\":false},"
|
|
||||||
+ "{\"c\":6,\"d\":true}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void arraysInObjects() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value(5);
|
|
||||||
writer.value(false);
|
|
||||||
writer.endArray();
|
|
||||||
writer.name("b");
|
|
||||||
writer.beginArray();
|
|
||||||
writer.value(6);
|
|
||||||
writer.value(true);
|
|
||||||
writer.endArray();
|
|
||||||
writer.endObject();
|
|
||||||
assertThat(factory.json()).isEqualTo("{\"a\":[5,false],"
|
|
||||||
+ "\"b\":[6,true]}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void deepNestingArrays() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
for (int i = 0; i < 31; i++) {
|
|
||||||
writer.beginArray();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 31; i++) {
|
|
||||||
writer.endArray();
|
|
||||||
}
|
|
||||||
assertThat(factory.json())
|
|
||||||
.isEqualTo("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void tooDeepNestingArrays() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
for (int i = 0; i < 31; i++) {
|
|
||||||
writer.beginArray();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.beginArray();
|
|
||||||
fail();
|
|
||||||
} catch (JsonDataException expected) {
|
|
||||||
assertThat(expected).hasMessage("Nesting too deep at $[0][0][0][0][0][0][0][0][0][0][0][0][0]"
|
|
||||||
+ "[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]: circular reference?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void deepNestingObjects() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
for (int i = 0; i < 31; i++) {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
}
|
|
||||||
writer.value(true);
|
|
||||||
for (int i = 0; i < 31; i++) {
|
|
||||||
writer.endObject();
|
|
||||||
}
|
|
||||||
assertThat(factory.json()).isEqualTo(""
|
|
||||||
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
|
|
||||||
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
|
|
||||||
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void tooDeepNestingObjects() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
for (int i = 0; i < 31; i++) {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.beginObject();
|
|
||||||
fail();
|
|
||||||
} catch (JsonDataException expected) {
|
|
||||||
assertThat(expected).hasMessage("Nesting too deep at $.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a."
|
|
||||||
+ "a.a.a.a.a.a.a.a.a.a.a.a: circular reference?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void repeatedName() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("a").value(true);
|
|
||||||
writer.name("a").value(false);
|
|
||||||
writer.endObject();
|
|
||||||
// JsonWriter doesn't attempt to detect duplicate names
|
|
||||||
assertThat(factory.json()).isEqualTo("{\"a\":true,\"a\":false}");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void prettyPrintObject() throws IOException {
|
@Test public void prettyPrintObject() throws IOException {
|
||||||
JsonWriter writer = factory.newWriter();
|
Buffer buffer = new Buffer();
|
||||||
|
JsonWriter writer = JsonWriter.of(buffer);
|
||||||
writer.setSerializeNulls(true);
|
writer.setSerializeNulls(true);
|
||||||
writer.setIndent(" ");
|
writer.setIndent(" ");
|
||||||
|
|
||||||
@@ -510,11 +57,12 @@ public final class BufferedSinkJsonWriterTest {
|
|||||||
+ " \"i\": 9.0\n"
|
+ " \"i\": 9.0\n"
|
||||||
+ " }\n"
|
+ " }\n"
|
||||||
+ "}";
|
+ "}";
|
||||||
assertThat(factory.json()).isEqualTo(expected);
|
assertThat(buffer.readUtf8()).isEqualTo(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void prettyPrintArray() throws IOException {
|
@Test public void prettyPrintArray() throws IOException {
|
||||||
JsonWriter writer = factory.newWriter();
|
Buffer buffer = new Buffer();
|
||||||
|
JsonWriter writer = JsonWriter.of(buffer);
|
||||||
writer.setIndent(" ");
|
writer.setIndent(" ");
|
||||||
|
|
||||||
writer.beginArray();
|
writer.beginArray();
|
||||||
@@ -546,99 +94,17 @@ public final class BufferedSinkJsonWriterTest {
|
|||||||
+ " 9.0\n"
|
+ " 9.0\n"
|
||||||
+ " ]\n"
|
+ " ]\n"
|
||||||
+ "]";
|
+ "]";
|
||||||
assertThat(factory.json()).isEqualTo(expected);
|
assertThat(buffer.readUtf8()).isEqualTo(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void lenientWriterPermitsMultipleTopLevelValues() throws IOException {
|
@Test public void repeatedNameIgnored() throws IOException {
|
||||||
JsonWriter writer = factory.newWriter();
|
Buffer buffer = new Buffer();
|
||||||
writer.setLenient(true);
|
JsonWriter writer = JsonWriter.of(buffer);
|
||||||
writer.beginArray();
|
writer.beginObject();
|
||||||
writer.endArray();
|
writer.name("a").value(1);
|
||||||
writer.beginArray();
|
writer.name("a").value(2);
|
||||||
writer.endArray();
|
writer.endObject();
|
||||||
writer.close();
|
// JsonWriter doesn't attempt to detect duplicate names
|
||||||
assertThat(factory.json()).isEqualTo("[][]");
|
assertThat(buffer.readUtf8()).isEqualTo("{\"a\":1,\"a\":2}");
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void strictWriterDoesNotPermitMultipleTopLevelValues() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
try {
|
|
||||||
writer.beginArray();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void closedWriterThrowsOnStructure() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
try {
|
|
||||||
writer.beginArray();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.endArray();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.beginObject();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.endObject();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void closedWriterThrowsOnName() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
try {
|
|
||||||
writer.name("a");
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void closedWriterThrowsOnValue() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
try {
|
|
||||||
writer.value("a");
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void closedWriterThrowsOnFlush() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
try {
|
|
||||||
writer.flush();
|
|
||||||
fail();
|
|
||||||
} catch (IllegalStateException expected) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void writerCloseIsIdempotent() throws IOException {
|
|
||||||
JsonWriter writer = factory.newWriter();
|
|
||||||
writer.beginArray();
|
|
||||||
writer.endArray();
|
|
||||||
writer.close();
|
|
||||||
writer.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ abstract class JsonReaderFactory {
|
|||||||
return JsonReader.of(buffer);
|
return JsonReader.of(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean supportsMultipleTopLevelValuesInOneDocument() {
|
@Override boolean supportsMultipleTopLevelValuesInOneDocument() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ abstract class JsonReaderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jwilson): fix precision checks and delete his method.
|
// TODO(jwilson): fix precision checks and delete his method.
|
||||||
@Override public boolean implementsStrictPrecision() {
|
@Override boolean implementsStrictPrecision() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,11 +61,11 @@ abstract class JsonReaderFactory {
|
|||||||
|
|
||||||
abstract JsonReader newReader(String json) throws IOException;
|
abstract JsonReader newReader(String json) throws IOException;
|
||||||
|
|
||||||
public boolean supportsMultipleTopLevelValuesInOneDocument() {
|
boolean supportsMultipleTopLevelValuesInOneDocument() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean implementsStrictPrecision() {
|
boolean implementsStrictPrecision() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,11 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package com.squareup.moshi;
|
package com.squareup.moshi;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
|
|
||||||
abstract class JsonWriterFactory {
|
abstract class JsonWriterFactory {
|
||||||
|
private static final Moshi MOSHI = new Moshi.Builder().build();
|
||||||
|
private static final JsonAdapter<Object> OBJECT_ADAPTER = MOSHI.adapter(Object.class);
|
||||||
|
|
||||||
static List<Object[]> factories() {
|
static List<Object[]> factories() {
|
||||||
final JsonWriterFactory bufferedSink = new JsonWriterFactory() {
|
final JsonWriterFactory bufferedSink = new JsonWriterFactory() {
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
@@ -35,15 +39,59 @@ abstract class JsonWriterFactory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override boolean supportsMultipleTopLevelValuesInOneDocument() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
return "BufferedSinkJsonWriter";
|
return "BufferedSinkJsonWriter";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Arrays.<Object[]>asList(
|
final JsonWriterFactory object = new JsonWriterFactory() {
|
||||||
new Object[] { bufferedSink });
|
ObjectJsonWriter writer;
|
||||||
|
|
||||||
|
@Override JsonWriter newWriter() {
|
||||||
|
writer = new ObjectJsonWriter();
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override String json() {
|
||||||
|
// This writer writes a DOM. Use other Moshi features to serialize it as a string.
|
||||||
|
try {
|
||||||
|
Buffer buffer = new Buffer();
|
||||||
|
JsonWriter bufferedSinkWriter = JsonWriter.of(buffer);
|
||||||
|
bufferedSinkWriter.setSerializeNulls(true);
|
||||||
|
OBJECT_ADAPTER.toJson(bufferedSinkWriter, writer.root());
|
||||||
|
return buffer.readUtf8();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jwilson): support BigDecimal and BigInteger and delete his method.
|
||||||
|
@Override boolean supportsBigNumbers() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String toString() {
|
||||||
|
return "ObjectJsonWriter";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Arrays.asList(
|
||||||
|
new Object[] { bufferedSink },
|
||||||
|
new Object[] { object });
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract JsonWriter newWriter();
|
abstract JsonWriter newWriter();
|
||||||
abstract String json();
|
abstract String json();
|
||||||
|
|
||||||
|
boolean supportsMultipleTopLevelValuesInOneDocument() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean supportsBigNumbers() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
565
moshi/src/test/java/com/squareup/moshi/JsonWriterTest.java
Normal file
565
moshi/src/test/java/com/squareup/moshi/JsonWriterTest.java
Normal file
@@ -0,0 +1,565 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.squareup.moshi;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameter;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public final class JsonWriterTest {
|
||||||
|
@Parameter public JsonWriterFactory factory;
|
||||||
|
|
||||||
|
@Parameters(name = "{0}")
|
||||||
|
public static List<Object[]> parameters() {
|
||||||
|
return JsonWriterFactory.factories();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nullsValuesNotSerializedByDefault() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
writer.nullValue();
|
||||||
|
writer.endObject();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nullsValuesSerializedWhenConfigured() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.setSerializeNulls(true);
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
writer.nullValue();
|
||||||
|
writer.endObject();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("{\"a\":null}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void topLevelBoolean() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.value(true);
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("true");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void topLevelNull() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.nullValue();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void topLevelInt() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.value(123);
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("123");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void topLevelDouble() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.value(123.4);
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("123.4");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void topLevelString() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.value("a");
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("\"a\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void invalidTopLevelTypes() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
try {
|
||||||
|
writer.name("hello").value("world");
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void twoNames() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
try {
|
||||||
|
writer.name("a");
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nameWithoutValue() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
try {
|
||||||
|
writer.endObject();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void valueWithoutName() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
try {
|
||||||
|
writer.value(true);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void multipleTopLevelValues() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray().endArray();
|
||||||
|
try {
|
||||||
|
writer.beginArray();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void badNestingObject() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.beginObject();
|
||||||
|
try {
|
||||||
|
writer.endArray();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void badNestingArray() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.beginArray();
|
||||||
|
try {
|
||||||
|
writer.endObject();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nullName() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
try {
|
||||||
|
writer.name(null);
|
||||||
|
fail();
|
||||||
|
} catch (NullPointerException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nullStringValue() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.setSerializeNulls(true);
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
writer.value((String) null);
|
||||||
|
writer.endObject();
|
||||||
|
assertThat(factory.json()).isEqualTo("{\"a\":null}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nonFiniteDoubles() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
try {
|
||||||
|
writer.value(Double.NaN);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.value(Double.NEGATIVE_INFINITY);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.value(Double.POSITIVE_INFINITY);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nonFiniteBoxedDoubles() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
try {
|
||||||
|
writer.value(new Double(Double.NaN));
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.value(new Double(Double.NEGATIVE_INFINITY));
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.value(new Double(Double.POSITIVE_INFINITY));
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void doubles() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value(-0.0);
|
||||||
|
writer.value(1.0);
|
||||||
|
writer.value(Double.MAX_VALUE);
|
||||||
|
writer.value(Double.MIN_VALUE);
|
||||||
|
writer.value(0.0);
|
||||||
|
writer.value(-0.5);
|
||||||
|
writer.value(2.2250738585072014E-308);
|
||||||
|
writer.value(Math.PI);
|
||||||
|
writer.value(Math.E);
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("[-0.0,"
|
||||||
|
+ "1.0,"
|
||||||
|
+ "1.7976931348623157E308,"
|
||||||
|
+ "4.9E-324,"
|
||||||
|
+ "0.0,"
|
||||||
|
+ "-0.5,"
|
||||||
|
+ "2.2250738585072014E-308,"
|
||||||
|
+ "3.141592653589793,"
|
||||||
|
+ "2.718281828459045]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void longs() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value(0);
|
||||||
|
writer.value(1);
|
||||||
|
writer.value(-1);
|
||||||
|
writer.value(Long.MIN_VALUE);
|
||||||
|
writer.value(Long.MAX_VALUE);
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("[0,"
|
||||||
|
+ "1,"
|
||||||
|
+ "-1,"
|
||||||
|
+ "-9223372036854775808,"
|
||||||
|
+ "9223372036854775807]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void numbers() throws IOException {
|
||||||
|
assumeTrue(factory.supportsBigNumbers());
|
||||||
|
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value(new BigInteger("0"));
|
||||||
|
writer.value(new BigInteger("9223372036854775808"));
|
||||||
|
writer.value(new BigInteger("-9223372036854775809"));
|
||||||
|
writer.value(new BigDecimal("3.141592653589793238462643383"));
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("[0,"
|
||||||
|
+ "9223372036854775808,"
|
||||||
|
+ "-9223372036854775809,"
|
||||||
|
+ "3.141592653589793238462643383]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void booleans() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value(true);
|
||||||
|
writer.value(false);
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[true,false]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void boxedBooleans() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value((Boolean) true);
|
||||||
|
writer.value((Boolean) false);
|
||||||
|
writer.value((Boolean) null);
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[true,false,null]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void nulls() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.nullValue();
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[null]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void strings() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value("a");
|
||||||
|
writer.value("a\"");
|
||||||
|
writer.value("\"");
|
||||||
|
writer.value(":");
|
||||||
|
writer.value(",");
|
||||||
|
writer.value("\b");
|
||||||
|
writer.value("\f");
|
||||||
|
writer.value("\n");
|
||||||
|
writer.value("\r");
|
||||||
|
writer.value("\t");
|
||||||
|
writer.value(" ");
|
||||||
|
writer.value("\\");
|
||||||
|
writer.value("{");
|
||||||
|
writer.value("}");
|
||||||
|
writer.value("[");
|
||||||
|
writer.value("]");
|
||||||
|
writer.value("\0");
|
||||||
|
writer.value("\u0019");
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[\"a\","
|
||||||
|
+ "\"a\\\"\","
|
||||||
|
+ "\"\\\"\","
|
||||||
|
+ "\":\","
|
||||||
|
+ "\",\","
|
||||||
|
+ "\"\\b\","
|
||||||
|
+ "\"\\f\","
|
||||||
|
+ "\"\\n\","
|
||||||
|
+ "\"\\r\","
|
||||||
|
+ "\"\\t\","
|
||||||
|
+ "\" \","
|
||||||
|
+ "\"\\\\\","
|
||||||
|
+ "\"{\","
|
||||||
|
+ "\"}\","
|
||||||
|
+ "\"[\","
|
||||||
|
+ "\"]\","
|
||||||
|
+ "\"\\u0000\","
|
||||||
|
+ "\"\\u0019\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void unicodeLineBreaksEscaped() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value("\u2028 \u2029");
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[\"\\u2028 \\u2029\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void emptyArray() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void emptyObject() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.endObject();
|
||||||
|
assertThat(factory.json()).isEqualTo("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void objectsInArrays() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a").value(5);
|
||||||
|
writer.name("b").value(false);
|
||||||
|
writer.endObject();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("c").value(6);
|
||||||
|
writer.name("d").value(true);
|
||||||
|
writer.endObject();
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[{\"a\":5,\"b\":false},"
|
||||||
|
+ "{\"c\":6,\"d\":true}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void arraysInObjects() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value(5);
|
||||||
|
writer.value(false);
|
||||||
|
writer.endArray();
|
||||||
|
writer.name("b");
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value(6);
|
||||||
|
writer.value(true);
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
assertThat(factory.json()).isEqualTo("{\"a\":[5,false],"
|
||||||
|
+ "\"b\":[6,true]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void deepNestingArrays() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
writer.beginArray();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
writer.endArray();
|
||||||
|
}
|
||||||
|
assertThat(factory.json())
|
||||||
|
.isEqualTo("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void tooDeepNestingArrays() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
writer.beginArray();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.beginArray();
|
||||||
|
fail();
|
||||||
|
} catch (JsonDataException expected) {
|
||||||
|
assertThat(expected).hasMessage("Nesting too deep at $[0][0][0][0][0][0][0][0][0][0][0][0][0]"
|
||||||
|
+ "[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]: circular reference?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void deepNestingObjects() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
}
|
||||||
|
writer.value(true);
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
writer.endObject();
|
||||||
|
}
|
||||||
|
assertThat(factory.json()).isEqualTo(""
|
||||||
|
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
|
||||||
|
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
|
||||||
|
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void tooDeepNestingObjects() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.beginObject();
|
||||||
|
fail();
|
||||||
|
} catch (JsonDataException expected) {
|
||||||
|
assertThat(expected).hasMessage("Nesting too deep at $.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a."
|
||||||
|
+ "a.a.a.a.a.a.a.a.a.a.a.a: circular reference?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void lenientWriterPermitsMultipleTopLevelValues() throws IOException {
|
||||||
|
assumeTrue(factory.supportsMultipleTopLevelValuesInOneDocument());
|
||||||
|
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.setLenient(true);
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
assertThat(factory.json()).isEqualTo("[][]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void strictWriterDoesNotPermitMultipleTopLevelValues() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
try {
|
||||||
|
writer.beginArray();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void closedWriterThrowsOnStructure() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
try {
|
||||||
|
writer.beginArray();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.endArray();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.beginObject();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
writer.endObject();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void closedWriterThrowsOnName() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
try {
|
||||||
|
writer.name("a");
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void closedWriterThrowsOnValue() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
try {
|
||||||
|
writer.value("a");
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void closedWriterThrowsOnFlush() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
try {
|
||||||
|
writer.flush();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void writerCloseIsIdempotent() throws IOException {
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
writer.endArray();
|
||||||
|
writer.close();
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
}
|
@@ -105,7 +105,7 @@ public final class MapJsonAdapterTest {
|
|||||||
fromJson(String.class, Integer.class, "{\"c\":1,\"c\":2}");
|
fromJson(String.class, Integer.class, "{\"c\":1,\"c\":2}");
|
||||||
fail();
|
fail();
|
||||||
} catch (JsonDataException expected) {
|
} catch (JsonDataException expected) {
|
||||||
assertThat(expected).hasMessage("Map key 'c' has multiple values at path $.c");
|
assertThat(expected).hasMessage("Map key 'c' has multiple values at path $.c: 1 and 2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Square, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.squareup.moshi;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
public final class ObjectJsonWriterTest {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test public void array() throws Exception {
|
||||||
|
ObjectJsonWriter writer = new ObjectJsonWriter();
|
||||||
|
|
||||||
|
writer.beginArray();
|
||||||
|
writer.value("s");
|
||||||
|
writer.value(1.5d);
|
||||||
|
writer.value(true);
|
||||||
|
writer.nullValue();
|
||||||
|
writer.endArray();
|
||||||
|
|
||||||
|
assertThat((List<Object>) writer.root()).containsExactly("s", 1.5d, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void object() throws Exception {
|
||||||
|
ObjectJsonWriter writer = new ObjectJsonWriter();
|
||||||
|
writer.setSerializeNulls(true);
|
||||||
|
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a").value("s");
|
||||||
|
writer.name("b").value(1.5d);
|
||||||
|
writer.name("c").value(true);
|
||||||
|
writer.name("d").nullValue();
|
||||||
|
writer.endObject();
|
||||||
|
|
||||||
|
assertThat((Map<?, ?>) writer.root()).containsExactly(
|
||||||
|
entry("a", "s"), entry("b", 1.5d), entry("c", true), entry("d", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void repeatedNameThrows() throws IOException {
|
||||||
|
ObjectJsonWriter writer = new ObjectJsonWriter();
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("a").value(1L);
|
||||||
|
try {
|
||||||
|
writer.name("a").value(2L);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
assertThat(expected).hasMessage(
|
||||||
|
"Map key 'a' has multiple values at path $.a: 1 and 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user