diff --git a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/DelegateKey.kt b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/DelegateKey.kt index 3165fed..c42ffce 100644 --- a/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/DelegateKey.kt +++ b/kotlin/codegen/src/main/java/com/squareup/moshi/kotlin/codegen/DelegateKey.kt @@ -69,11 +69,9 @@ internal data class DelegateKey( } val finalArgs = arrayOf(*standardArgs, *args) - val nullModifier = if (nullable) ".nullSafe()" else ".nonNull()" - return PropertySpec.builder(adapterName, adapterTypeName, KModifier.PRIVATE) .addAnnotations(jsonQualifiers) - .initializer("%1N.adapter%2L(%3L$initializerString)$nullModifier", *finalArgs) + .initializer("%1N.adapter%2L(%3L$initializerString)", *finalArgs) .build() } } diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codgen/GeneratedAdaptersTest.kt b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codgen/GeneratedAdaptersTest.kt index be90a49..793cdb9 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codgen/GeneratedAdaptersTest.kt +++ b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/codgen/GeneratedAdaptersTest.kt @@ -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 diff --git a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt index 89b21de..8993837 100644 --- a/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt +++ b/kotlin/tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt @@ -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())