mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 16:09:21 +08:00
Add coherent error message for unencoded map keys.
This commit is contained in:
@@ -77,6 +77,10 @@ final class JsonUtf8Writer extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter beginArray() throws IOException {
|
@Override public JsonWriter beginArray() throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Array cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
writeDeferredName();
|
writeDeferredName();
|
||||||
return open(EMPTY_ARRAY, "[");
|
return open(EMPTY_ARRAY, "[");
|
||||||
}
|
}
|
||||||
@@ -86,6 +90,10 @@ final class JsonUtf8Writer extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter beginObject() throws IOException {
|
@Override public JsonWriter beginObject() throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Object cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
writeDeferredName();
|
writeDeferredName();
|
||||||
return open(EMPTY_OBJECT, "{");
|
return open(EMPTY_OBJECT, "{");
|
||||||
}
|
}
|
||||||
@@ -171,6 +179,10 @@ final class JsonUtf8Writer extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter nullValue() throws IOException {
|
@Override public JsonWriter nullValue() throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"null cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
if (deferredName != null) {
|
if (deferredName != null) {
|
||||||
if (serializeNulls) {
|
if (serializeNulls) {
|
||||||
writeDeferredName();
|
writeDeferredName();
|
||||||
@@ -186,6 +198,10 @@ final class JsonUtf8Writer extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(boolean value) throws IOException {
|
@Override public JsonWriter value(boolean value) throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Boolean cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
writeDeferredName();
|
writeDeferredName();
|
||||||
beforeValue();
|
beforeValue();
|
||||||
sink.writeUtf8(value ? "true" : "false");
|
sink.writeUtf8(value ? "true" : "false");
|
||||||
|
@@ -47,6 +47,10 @@ final class JsonValueWriter extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter beginArray() throws IOException {
|
@Override public JsonWriter beginArray() throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Array cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
checkStack();
|
checkStack();
|
||||||
List<Object> list = new ArrayList<>();
|
List<Object> list = new ArrayList<>();
|
||||||
add(list);
|
add(list);
|
||||||
@@ -67,6 +71,10 @@ final class JsonValueWriter extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter beginObject() throws IOException {
|
@Override public JsonWriter beginObject() throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Object cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
checkStack();
|
checkStack();
|
||||||
Map<String, Object> map = new LinkedHashTreeMap<>();
|
Map<String, Object> map = new LinkedHashTreeMap<>();
|
||||||
add(map);
|
add(map);
|
||||||
@@ -116,18 +124,30 @@ final class JsonValueWriter extends JsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter nullValue() throws IOException {
|
@Override public JsonWriter nullValue() throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"null cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
add(null);
|
add(null);
|
||||||
pathIndices[stackSize - 1]++;
|
pathIndices[stackSize - 1]++;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(boolean value) throws IOException {
|
@Override public JsonWriter value(boolean value) throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Boolean cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
add(value);
|
add(value);
|
||||||
pathIndices[stackSize - 1]++;
|
pathIndices[stackSize - 1]++;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(@Nullable Boolean value) throws IOException {
|
@Override public JsonWriter value(@Nullable Boolean value) throws IOException {
|
||||||
|
if (promoteValueToName) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Boolean cannot be used as a map key in JSON at path " + getPath());
|
||||||
|
}
|
||||||
add(value);
|
add(value);
|
||||||
pathIndices[stackSize - 1]++;
|
pathIndices[stackSize - 1]++;
|
||||||
return this;
|
return this;
|
||||||
|
@@ -141,6 +141,65 @@ public final class MapJsonAdapterTest {
|
|||||||
assertThat(jsonAdapter.fromJsonValue(jsonObject)).isEqualTo(map);
|
assertThat(jsonAdapter.fromJsonValue(jsonObject)).isEqualTo(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void booleanKeyTypeHasCoherentErrorMessage() {
|
||||||
|
Map<Boolean, String> map = new LinkedHashMap<>();
|
||||||
|
map.put(true, "");
|
||||||
|
JsonAdapter<Map<Boolean, String>> adapter = mapAdapter(Boolean.class, String.class);
|
||||||
|
try {
|
||||||
|
adapter.toJson(map);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
assertThat(expected).hasMessage("Boolean cannot be used as a map key in JSON at path $.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
adapter.toJsonValue(map);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
assertThat(expected).hasMessage("Boolean cannot be used as a map key in JSON at path $.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class Key {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void objectKeyTypeHasCoherentErrorMessage() {
|
||||||
|
Map<Key, String> map = new LinkedHashMap<>();
|
||||||
|
map.put(new Key(), "");
|
||||||
|
JsonAdapter<Map<Key, String>> adapter = mapAdapter(Key.class, String.class);
|
||||||
|
try {
|
||||||
|
adapter.toJson(map);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
assertThat(expected).hasMessage("Object cannot be used as a map key in JSON at path $.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
adapter.toJsonValue(map);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
assertThat(expected).hasMessage("Object cannot be "
|
||||||
|
+ "used as a map key in JSON at path $.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void arrayKeyTypeHasCoherentErrorMessage() {
|
||||||
|
Map<String[], String> map = new LinkedHashMap<>();
|
||||||
|
map.put(new String[0], "");
|
||||||
|
JsonAdapter<Map<String[], String>> adapter =
|
||||||
|
mapAdapter(Types.arrayOf(String.class), String.class);
|
||||||
|
try {
|
||||||
|
adapter.toJson(map);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
assertThat(expected).hasMessage("Array cannot be used as a map key in JSON at path $.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
adapter.toJsonValue(map);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
assertThat(expected).hasMessage("Array cannot be used as a map key in JSON at path $.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <K, V> String toJson(Type keyType, Type valueType, Map<K, V> value) throws IOException {
|
private <K, V> String toJson(Type keyType, Type valueType, Map<K, V> value) throws IOException {
|
||||||
JsonAdapter<Map<K, V>> jsonAdapter = mapAdapter(keyType, valueType);
|
JsonAdapter<Map<K, V>> jsonAdapter = mapAdapter(keyType, valueType);
|
||||||
Buffer buffer = new Buffer();
|
Buffer buffer = new Buffer();
|
||||||
|
@@ -252,7 +252,7 @@ public final class PromoteNameToValueTest {
|
|||||||
writer.value(true);
|
writer.value(true);
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
assertThat(e).hasMessage("Nesting problem.");
|
assertThat(e).hasMessage("Boolean cannot be used as a map key in JSON at path $.");
|
||||||
}
|
}
|
||||||
writer.value("true");
|
writer.value("true");
|
||||||
assertThat(writer.getPath()).isEqualTo("$.true");
|
assertThat(writer.getPath()).isEqualTo("$.true");
|
||||||
@@ -283,7 +283,7 @@ public final class PromoteNameToValueTest {
|
|||||||
writer.nullValue();
|
writer.nullValue();
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
assertThat(e).hasMessage("Nesting problem.");
|
assertThat(e).hasMessage("null cannot be used as a map key in JSON at path $.");
|
||||||
}
|
}
|
||||||
writer.value("null");
|
writer.value("null");
|
||||||
assertThat(writer.getPath()).isEqualTo("$.null");
|
assertThat(writer.getPath()).isEqualTo("$.null");
|
||||||
|
Reference in New Issue
Block a user