Allow user adapters to convert null to non-null in codegen.

Delegate to installed adapters instead of checking for null.
This commit is contained in:
Eric Cochran
2018-09-11 01:02:38 -07:00
parent 9050e42038
commit 8e151b1df3
3 changed files with 79 additions and 7 deletions

View File

@@ -413,7 +413,7 @@ class GeneratedAdaptersTest {
jsonAdapter.fromJson("{\"a\":null}")
fail()
} catch (expected: JsonDataException) {
assertThat(expected).hasMessage("Unexpected null at \$.a")
assertThat(expected).hasMessage("Non-null value 'a' was null at \$.a")
}
}
@@ -432,7 +432,10 @@ class GeneratedAdaptersTest {
}
@JsonClass(generateAdapter = true)
class HasNonNullConstructorParameter(val a: String)
data class HasNonNullConstructorParameter(val a: String)
@JsonClass(generateAdapter = true)
data class HasNullableConstructorParameter(val a: String?)
@Test fun explicitNull() {
val moshi = Moshi.Builder().build()
@@ -592,7 +595,7 @@ class GeneratedAdaptersTest {
jsonAdapter.fromJson("{\"a\":null}")
fail()
} catch (expected: JsonDataException) {
assertThat(expected).hasMessage("Unexpected null at \$.a")
assertThat(expected).hasMessage("Non-null value 'a' was null at \$.a")
}
}
@@ -1083,6 +1086,50 @@ class GeneratedAdaptersTest {
assertThat(adapter.fromJson("null")).isNull()
assertThat(adapter.toJson(null)).isEqualTo("null")
}
@Retention(AnnotationRetention.RUNTIME)
annotation class Nullable
@Test fun delegatesToInstalledAdaptersBeforeNullChecking() {
val moshi = Moshi.Builder()
.add(object {
@FromJson fun fromJson(@Nullable string: String?): String {
return string ?: "fallback"
}
@ToJson fun toJson(@Nullable value: String?): String {
return value ?: "fallback"
}
})
.build()
val hasNonNullConstructorParameterAdapter =
moshi.adapter(HasNonNullConstructorParameter::class.java)
assertThat(hasNonNullConstructorParameterAdapter
.fromJson("{\"a\":null}")).isEqualTo(HasNonNullConstructorParameter("fallback"))
val hasNullableConstructorParameterAdapter =
moshi.adapter(HasNullableConstructorParameter::class.java)
assertThat(hasNullableConstructorParameterAdapter
.fromJson("{\"a\":null}")).isEqualTo(HasNullableConstructorParameter("fallback"))
assertThat(hasNullableConstructorParameterAdapter
.toJson(HasNullableConstructorParameter(null))).isEqualTo("{\"a\":\"fallback\"}")
}
@JsonClass(generateAdapter = true)
data class HasNullableTypeWithGeneratedAdapter(val a: HasNonNullConstructorParameter?)
@Test fun delegatesToInstalledAdaptersBeforeNullCheckingWithGeneratedAdapter() {
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(HasNullableTypeWithGeneratedAdapter::class.java)
val encoded = HasNullableTypeWithGeneratedAdapter(null)
assertThat(adapter.toJson(encoded)).isEqualTo("""{}""")
assertThat(adapter.serializeNulls().toJson(encoded)).isEqualTo("""{"a":null}""")
val decoded = adapter.fromJson("""{"a":null}""")!!
assertThat(decoded.a).isEqualTo(null)
}
}
// Has to be outside to avoid Types seeing an owning class

View File

@@ -170,7 +170,9 @@ class KotlinJsonAdapterTest {
}
}
class HasNonNullConstructorParameter(val a: String)
data class HasNonNullConstructorParameter(val a: String)
data class HasNullableConstructorParameter(val a: String?)
@Test fun nonNullPropertySetToNullFailsWithJsonDataException() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
@@ -853,6 +855,31 @@ class KotlinJsonAdapterTest {
assertThat(adapter.toJson(value)).isEqualTo(json)
}
@Retention(RUNTIME)
annotation class Nullable
@Test fun delegatesToInstalledAdaptersBeforeNullChecking() {
val moshi = Moshi.Builder()
.add(object {
@FromJson fun fromJson(@Nullable string: String?): String {
return string ?: "fallback"
}
@ToJson fun toJson(@Nullable value: String?): String {
return value ?: "fallback"
}
})
.build()
assertThat(moshi.adapter(HasNonNullConstructorParameter::class.java)
.fromJson("{\"a\":null}")).isEqualTo(HasNonNullConstructorParameter("fallback"))
assertThat(moshi.adapter(HasNullableConstructorParameter::class.java)
.fromJson("{\"a\":null}")).isEqualTo(HasNullableConstructorParameter("fallback"))
assertThat(moshi.adapter(HasNullableConstructorParameter::class.java)
.toJson(HasNullableConstructorParameter(null))).isEqualTo("{\"a\":\"fallback\"}")
}
@Test fun mixingReflectionAndCodegen() {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())