mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 16:09:21 +08:00
JsonAdapter.nonNull() forbids explicit nulls in the JSON body
This adapter modifier throws exceptions if an unexpected null is encountered. This may pair nicely with Kotlin.
This commit is contained in:
@@ -196,7 +196,7 @@ class JsonClassCodeGenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
|
|||||||
|
|
||||||
val hasDefault = parameter?.declaresDefaultValue ?: true
|
val hasDefault = parameter?.declaresDefaultValue ?: true
|
||||||
|
|
||||||
if (enclosedElement.modifiers.contains(Modifier.TRANSIENT)) {
|
if (Modifier.TRANSIENT in enclosedElement.modifiers) {
|
||||||
if (!hasDefault) {
|
if (!hasDefault) {
|
||||||
throw IllegalArgumentException("No default value for transient property $name")
|
throw IllegalArgumentException("No default value for transient property $name")
|
||||||
}
|
}
|
||||||
|
@@ -153,6 +153,39 @@ public abstract class JsonAdapter<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON adapter equal to this JSON adapter, but that refuses null values. If null is
|
||||||
|
* read or written this will throw a {@link JsonDataException}.
|
||||||
|
*
|
||||||
|
* <p>Note that this adapter will not usually be invoked for absent values and so those must be
|
||||||
|
* handled elsewhere. This should only be used to fail on explicit nulls.
|
||||||
|
*/
|
||||||
|
@CheckReturnValue public final JsonAdapter<T> nonNull() {
|
||||||
|
final JsonAdapter<T> delegate = this;
|
||||||
|
return new JsonAdapter<T>() {
|
||||||
|
@Override public @Nullable T fromJson(JsonReader reader) throws IOException {
|
||||||
|
if (reader.peek() == JsonReader.Token.NULL) {
|
||||||
|
throw new JsonDataException("Unexpected null at " + reader.getPath());
|
||||||
|
} else {
|
||||||
|
return delegate.fromJson(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override public void toJson(JsonWriter writer, @Nullable T value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
throw new JsonDataException("Unexpected null at " + writer.getPath());
|
||||||
|
} else {
|
||||||
|
delegate.toJson(writer, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override boolean isLenient() {
|
||||||
|
return delegate.isLenient();
|
||||||
|
}
|
||||||
|
@Override public String toString() {
|
||||||
|
return delegate + ".nonNull()";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns a JSON adapter equal to this, but is lenient when reading and writing. */
|
/** Returns a JSON adapter equal to this, but is lenient when reading and writing. */
|
||||||
@CheckReturnValue public final JsonAdapter<T> lenient() {
|
@CheckReturnValue public final JsonAdapter<T> lenient() {
|
||||||
final JsonAdapter<T> delegate = this;
|
final JsonAdapter<T> delegate = this;
|
||||||
|
@@ -95,6 +95,45 @@ public final class JsonAdapterTest {
|
|||||||
assertThat(factory.json()).isEqualTo("[\"A\",null,\"C\"]");
|
assertThat(factory.json()).isEqualTo("[\"A\",null,\"C\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void nonNull() throws Exception {
|
||||||
|
JsonAdapter<String> toUpperCase = new JsonAdapter<String>() {
|
||||||
|
@Override public String fromJson(JsonReader reader) throws IOException {
|
||||||
|
return reader.nextString().toUpperCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void toJson(JsonWriter writer, String value) throws IOException {
|
||||||
|
writer.value(value.toUpperCase(Locale.US));
|
||||||
|
}
|
||||||
|
}.nonNull();
|
||||||
|
|
||||||
|
JsonReader reader = factory.newReader("[\"a\", null, \"c\"]");
|
||||||
|
reader.beginArray();
|
||||||
|
assertThat(toUpperCase.fromJson(reader)).isEqualTo("A");
|
||||||
|
try {
|
||||||
|
toUpperCase.fromJson(reader);
|
||||||
|
fail();
|
||||||
|
} catch (JsonDataException expected) {
|
||||||
|
assertThat(expected).hasMessage("Unexpected null at $[1]");
|
||||||
|
assertThat(reader.nextNull()).isNull();
|
||||||
|
}
|
||||||
|
assertThat(toUpperCase.fromJson(reader)).isEqualTo("C");
|
||||||
|
reader.endArray();
|
||||||
|
|
||||||
|
JsonWriter writer = factory.newWriter();
|
||||||
|
writer.beginArray();
|
||||||
|
toUpperCase.toJson(writer, "a");
|
||||||
|
try {
|
||||||
|
toUpperCase.toJson(writer, null);
|
||||||
|
fail();
|
||||||
|
} catch (JsonDataException expected) {
|
||||||
|
assertThat(expected).hasMessage("Unexpected null at $[1]");
|
||||||
|
writer.nullValue();
|
||||||
|
}
|
||||||
|
toUpperCase.toJson(writer, "c");
|
||||||
|
writer.endArray();
|
||||||
|
assertThat(factory.json()).isEqualTo("[\"A\",null,\"C\"]");
|
||||||
|
}
|
||||||
|
|
||||||
@Test public void failOnUnknown() throws Exception {
|
@Test public void failOnUnknown() throws Exception {
|
||||||
JsonAdapter<String> alwaysSkip = new JsonAdapter<String>() {
|
JsonAdapter<String> alwaysSkip = new JsonAdapter<String>() {
|
||||||
@Override public String fromJson(JsonReader reader) throws IOException {
|
@Override public String fromJson(JsonReader reader) throws IOException {
|
||||||
|
Reference in New Issue
Block a user