From 9db91f2dcebf3b544c60b34141d2ee1cb39cc69d Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Wed, 4 Sep 2019 20:24:59 -0400 Subject: [PATCH] Kotlin-reflect QoL APIs (#875) * Start MoshiKotlinExtensions * Add Moshi.Builder.add() with reified typeOf * Use non-shadowing name for addAdapter * Implement KType.toType() .javaType isn't implemented * Don't re-wrap wrapped adapters * Use new adapter functions in tests to smoke test * Don't enable uses experimental in kotlin-reflect, only the test * Use internal leniency API * Use toType in addAdapter too * Update error message in test --- .../kotlin/reflect/-MoshiKotlinExtensions.kt | 89 +++++++++++++++ .../kotlin/reflect/KotlinJsonAdapterTest.kt | 6 +- kotlin/tests/pom.xml | 1 + .../kotlin/codgen/GeneratedAdaptersTest.kt | 108 +++++++++--------- .../kotlin/reflect/KotlinJsonAdapterTest.kt | 108 +++++++++--------- .../java/com/squareup/moshi/JsonAdapter.java | 25 +--- .../moshi/internal/NonNullJsonAdapter.java | 60 ++++++++++ .../com/squareup/moshi/JsonAdapterTest.java | 2 +- 8 files changed, 267 insertions(+), 132 deletions(-) create mode 100644 kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/-MoshiKotlinExtensions.kt create mode 100644 moshi/src/main/java/com/squareup/moshi/internal/NonNullJsonAdapter.java diff --git a/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/-MoshiKotlinExtensions.kt b/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/-MoshiKotlinExtensions.kt new file mode 100644 index 0000000..ec9d3b7 --- /dev/null +++ b/kotlin/reflect/src/main/java/com/squareup/moshi/kotlin/reflect/-MoshiKotlinExtensions.kt @@ -0,0 +1,89 @@ +package com.squareup.moshi.kotlin.reflect + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import com.squareup.moshi.internal.NonNullJsonAdapter +import com.squareup.moshi.internal.NullSafeJsonAdapter +import java.lang.reflect.Type +import kotlin.reflect.KClass +import kotlin.reflect.KType +import kotlin.reflect.KTypeParameter +import kotlin.reflect.KTypeProjection +import kotlin.reflect.KVariance +import kotlin.reflect.typeOf + +/** + * @return a [JsonAdapter] for [T], creating it if necessary. Note that while nullability of [T] + * itself is handled, nested types (such as in generics) are not resolved. + */ +@ExperimentalStdlibApi +inline fun Moshi.adapter(): JsonAdapter { + return adapter(typeOf()) +} + +@ExperimentalStdlibApi +inline fun Moshi.Builder.addAdapter(adapter: JsonAdapter) = add(typeOf().toType(), adapter) + +/** + * @return a [JsonAdapter] for [ktype], creating it if necessary. Note that while nullability of + * [ktype] itself is handled, nested types (such as in generics) are not resolved. + */ +fun Moshi.adapter(ktype: KType): JsonAdapter { + val adapter = adapter(ktype.toType()) + return if (adapter is NullSafeJsonAdapter || adapter is NonNullJsonAdapter) { + // TODO CR - Assume that these know what they're doing? Or should we defensively avoid wrapping for matching nullability? + adapter + } else if (ktype.isMarkedNullable) { + adapter.nullSafe() + } else { + adapter.nonNull() + } +} + +@PublishedApi +internal fun KType.toType(): Type { + classifier?.let { + when (it) { + is KTypeParameter -> throw IllegalArgumentException("Type parameters are not supported") + is KClass<*> -> { + val javaType = it.java + if (javaType.isArray) { + return Types.arrayOf(javaType.componentType) + } + + return if (arguments.isEmpty()) { + javaType + } else { + val typeArguments = arguments.toTypedArray { it.toType() } + val enclosingClass = javaType.enclosingClass + return if (enclosingClass != null) { + Types.newParameterizedTypeWithOwner(enclosingClass, javaType, *typeArguments) + } else { + Types.newParameterizedType(javaType, *typeArguments) + } + } + } + else -> throw IllegalArgumentException("Unsupported classifier: $this") + } + } + + // Can happen for intersection types + throw IllegalArgumentException("Unrepresentable type: $this") +} + +internal fun KTypeProjection.toType(): Type { + val javaType = type?.toType() ?: return Any::class.java + return when (variance) { + null -> Any::class.java + KVariance.INVARIANT -> javaType + KVariance.IN -> Types.subtypeOf(javaType) + KVariance.OUT -> Types.supertypeOf(javaType) + } +} + +private inline fun List.toTypedArray(mapper: (T) -> R): Array { + return Array(size) { + mapper.invoke(get(it)) + } +} diff --git a/kotlin/reflect/src/main/test/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt b/kotlin/reflect/src/main/test/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt index c770242..7b88235 100644 --- a/kotlin/reflect/src/main/test/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt +++ b/kotlin/reflect/src/main/test/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt @@ -9,11 +9,13 @@ class KotlinJsonAdapterTest { @JsonClass(generateAdapter = true) class Data - @Test fun fallsBackToReflectiveAdapterWithoutCodegen() { + @ExperimentalStdlibApi + @Test + fun fallsBackToReflectiveAdapterWithoutCodegen() { val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() - val adapter = moshi.adapter(Data::class.java) + val adapter = moshi.adapter() assertThat(adapter.toString()).isEqualTo( "KotlinJsonAdapter(com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterTest.Data).nullSafe()" ) diff --git a/kotlin/tests/pom.xml b/kotlin/tests/pom.xml index fb1523e..eb2d813 100644 --- a/kotlin/tests/pom.xml +++ b/kotlin/tests/pom.xml @@ -116,6 +116,7 @@ -Werror + -Xuse-experimental=kotlin.ExperimentalStdlibApi 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 3793881..eb86445 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 @@ -27,6 +27,7 @@ import com.squareup.moshi.Moshi import com.squareup.moshi.ToJson import com.squareup.moshi.Types import com.squareup.moshi.internal.NullSafeJsonAdapter +import com.squareup.moshi.kotlin.reflect.adapter import org.assertj.core.api.Assertions.assertThat import org.intellij.lang.annotations.Language import org.junit.Assert.assertNull @@ -36,6 +37,7 @@ import org.junit.Test import java.util.Locale import kotlin.reflect.full.memberProperties +@ExperimentalStdlibApi @Suppress("UNUSED", "UNUSED_PARAMETER") class GeneratedAdaptersTest { @@ -43,7 +45,7 @@ class GeneratedAdaptersTest { @Test fun jsonAnnotation() { - val adapter = moshi.adapter(JsonAnnotation::class.java) + val adapter = moshi.adapter() // Read @Language("JSON") @@ -64,7 +66,7 @@ class GeneratedAdaptersTest { @Test fun jsonAnnotationWithDollarSign() { - val adapter = moshi.adapter(JsonAnnotationWithDollarSign::class.java) + val adapter = moshi.adapter() // Read val json = "{\"\$foo\": \"bar\"}" @@ -83,7 +85,7 @@ class GeneratedAdaptersTest { @Test fun defaultValues() { - val adapter = moshi.adapter(DefaultValues::class.java) + val adapter = moshi.adapter() // Read/write with default values @Language("JSON") @@ -124,7 +126,7 @@ class GeneratedAdaptersTest { @Test fun nullableArray() { - val adapter = moshi.adapter(NullableArray::class.java) + val adapter = moshi.adapter() @Language("JSON") val json = """{"data":[null,"why"]}""" @@ -139,7 +141,7 @@ class GeneratedAdaptersTest { @Test fun primitiveArray() { - val adapter = moshi.adapter(PrimitiveArray::class.java) + val adapter = moshi.adapter() @Language("JSON") val json = """{"ints":[0,1]}""" @@ -154,7 +156,7 @@ class GeneratedAdaptersTest { @Test fun nullableTypes() { - val adapter = moshi.adapter(NullabeTypes::class.java) + val adapter = moshi.adapter() @Language("JSON") val json = """{"foo":"foo","nullableString":null}""" @@ -181,7 +183,7 @@ class GeneratedAdaptersTest { @Test fun collections() { - val adapter = moshi.adapter(SpecialCollections::class.java) + val adapter = moshi.adapter() val specialCollections = SpecialCollections( mutableListOf(), @@ -209,7 +211,7 @@ class GeneratedAdaptersTest { @Test fun mutableProperties() { - val adapter = moshi.adapter(MutableProperties::class.java) + val adapter = moshi.adapter() val mutableProperties = MutableProperties( "immutableProperty", @@ -301,7 +303,7 @@ class GeneratedAdaptersTest { @Test fun constructorParameters() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -316,7 +318,7 @@ class GeneratedAdaptersTest { @Test fun properties() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(Properties::class.java) + val jsonAdapter = moshi.adapter() val encoded = Properties() encoded.a = 3 @@ -336,7 +338,7 @@ class GeneratedAdaptersTest { @Test fun constructorParametersAndProperties() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ConstructorParametersAndProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParametersAndProperties(3) encoded.b = 5 @@ -354,7 +356,7 @@ class GeneratedAdaptersTest { @Test fun immutableConstructorParameters() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ImmutableConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = ImmutableConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -369,7 +371,7 @@ class GeneratedAdaptersTest { @Test fun immutableProperties() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ImmutableProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = ImmutableProperties(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -387,7 +389,7 @@ class GeneratedAdaptersTest { @Test fun constructorDefaults() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ConstructorDefaultValues::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorDefaultValues(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -402,7 +404,7 @@ class GeneratedAdaptersTest { @Test fun requiredValueAbsent() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(RequiredValueAbsent::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4}""") @@ -417,7 +419,7 @@ class GeneratedAdaptersTest { @Test fun nonNullConstructorParameterCalledWithNullFailsWithJsonDataException() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":null}") @@ -431,7 +433,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder().add(object { @FromJson fun fromJson(string: String): String? = null }).build() - val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":\"hello\"}") @@ -449,7 +451,7 @@ class GeneratedAdaptersTest { @Test fun explicitNull() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ExplicitNull::class.java) + val jsonAdapter = moshi.adapter() val encoded = ExplicitNull(null, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""") @@ -465,7 +467,7 @@ class GeneratedAdaptersTest { @Test fun absentNull() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(AbsentNull::class.java) + val jsonAdapter = moshi.adapter() val encoded = AbsentNull(null, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""") @@ -483,7 +485,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder() .add(UppercaseJsonAdapter()) .build() - val jsonAdapter = moshi.adapter(ConstructorParameterWithQualifier::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParameterWithQualifier("Android", "Banana") assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":"ANDROID","b":"Banana"}""") @@ -500,7 +502,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder() .add(UppercaseJsonAdapter()) .build() - val jsonAdapter = moshi.adapter(PropertyWithQualifier::class.java) + val jsonAdapter = moshi.adapter() val encoded = PropertyWithQualifier() encoded.a = "Android" @@ -520,7 +522,7 @@ class GeneratedAdaptersTest { @Test fun constructorParameterWithJsonName() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ConstructorParameterWithJsonName::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParameterWithJsonName(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"key a":3,"b":5}""") @@ -535,7 +537,7 @@ class GeneratedAdaptersTest { @Test fun propertyWithJsonName() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(PropertyWithJsonName::class.java) + val jsonAdapter = moshi.adapter() val encoded = PropertyWithJsonName() encoded.a = 3 @@ -555,7 +557,7 @@ class GeneratedAdaptersTest { @Test fun transientConstructorParameter() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(TransientConstructorParameter::class.java) + val jsonAdapter = moshi.adapter() val encoded = TransientConstructorParameter(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""") @@ -570,7 +572,7 @@ class GeneratedAdaptersTest { @Test fun transientProperty() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(TransientProperty::class.java) + val jsonAdapter = moshi.adapter() val encoded = TransientProperty() encoded.a = 3 @@ -599,7 +601,7 @@ class GeneratedAdaptersTest { @Test fun nonNullPropertySetToNullFailsWithJsonDataException() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":null}") @@ -613,7 +615,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder().add(object { @FromJson fun fromJson(string: String): String? = null }).build() - val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":\"hello\"}") @@ -630,7 +632,7 @@ class GeneratedAdaptersTest { @Test fun manyProperties32() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ManyProperties32::class.java) + val jsonAdapter = moshi.adapter() val encoded = ManyProperties32( 101, 102, 103, 104, 105, @@ -671,7 +673,7 @@ class GeneratedAdaptersTest { @Test fun manyProperties33() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ManyProperties33::class.java) + val jsonAdapter = moshi.adapter() val encoded = ManyProperties33( 101, 102, 103, 104, 105, @@ -713,7 +715,7 @@ class GeneratedAdaptersTest { @Test fun unsettablePropertyIgnored() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(UnsettableProperty::class.java) + val jsonAdapter = moshi.adapter() val encoded = UnsettableProperty() encoded.b = 5 @@ -732,7 +734,7 @@ class GeneratedAdaptersTest { @Test fun getterOnlyNoBackingField() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(GetterOnly::class.java) + val jsonAdapter = moshi.adapter() val encoded = GetterOnly(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -751,7 +753,7 @@ class GeneratedAdaptersTest { @Test fun getterAndSetterNoBackingField() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(GetterAndSetter::class.java) + val jsonAdapter = moshi.adapter() val encoded = GetterAndSetter(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5,"total":8}""") @@ -780,7 +782,7 @@ class GeneratedAdaptersTest { @Test fun supertypeConstructorParameters() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(SubtypeConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = SubtypeConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -797,7 +799,7 @@ class GeneratedAdaptersTest { @Test fun supertypeProperties() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(SubtypeProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = SubtypeProperties() encoded.a = 3 @@ -821,7 +823,7 @@ class GeneratedAdaptersTest { /** Generated adapters don't track enough state to detect duplicated values. */ @Ignore @Test fun duplicatedValueParameter() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(DuplicateValueParameter::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4,"a":4}""") @@ -836,7 +838,7 @@ class GeneratedAdaptersTest { /** Generated adapters don't track enough state to detect duplicated values. */ @Ignore @Test fun duplicatedValueProperty() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(DuplicateValueProperty::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4,"a":4}""") @@ -853,7 +855,7 @@ class GeneratedAdaptersTest { @Test fun extensionProperty() { val moshi = Moshi.Builder().build() - val jsonAdapter = moshi.adapter(ExtensionProperty::class.java) + val jsonAdapter = moshi.adapter() val encoded = ExtensionProperty(3) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3}""") @@ -878,7 +880,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder() .add(UppercaseJsonAdapter()) .build() - val jsonAdapter = moshi.adapter(MultiplePropertiesShareAdapter::class.java) + val jsonAdapter = moshi.adapter() val encoded = MultiplePropertiesShareAdapter("Android", "Banana") assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":"ANDROID","b":"BANANA"}""") @@ -900,7 +902,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder() .add(CustomToJsonOnlyAdapter()) .build() - val jsonAdapter = moshi.adapter(CustomToJsonOnly::class.java) + val jsonAdapter = moshi.adapter() assertThat(jsonAdapter.toJson(CustomToJsonOnly(1, 2))).isEqualTo("""[1,2]""") @@ -922,7 +924,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder() .add(CustomFromJsonOnlyAdapter()) .build() - val jsonAdapter = moshi.adapter(CustomFromJsonOnly::class.java) + val jsonAdapter = moshi.adapter() assertThat(jsonAdapter.toJson(CustomFromJsonOnly(1, 2))).isEqualTo("""{"a":1,"b":2}""") @@ -941,7 +943,7 @@ class GeneratedAdaptersTest { } @Test fun privateTransientIsIgnored() { - val jsonAdapter = moshi.adapter(PrivateTransient::class.java) + val jsonAdapter = moshi.adapter() val privateTransient = PrivateTransient() privateTransient.writeA(1) @@ -971,7 +973,7 @@ class GeneratedAdaptersTest { val moshi = Moshi.Builder() .add(NothingAdapter()) .build() - val jsonAdapter = moshi.adapter(HasNothingProperty::class.java).serializeNulls() + val jsonAdapter = moshi.adapter().serializeNulls() val toJson = HasNothingProperty() toJson.a = "1" @@ -1000,7 +1002,7 @@ class GeneratedAdaptersTest { } @Test fun enclosedParameterizedType() { - val jsonAdapter = moshi.adapter(HasParameterizedProperty::class.java) + val jsonAdapter = moshi.adapter() assertThat(jsonAdapter.toJson(HasParameterizedProperty(Twins("1", "2")))) .isEqualTo("""{"twins":{"a":"1","b":"2"}}""") @@ -1017,7 +1019,7 @@ class GeneratedAdaptersTest { class HasParameterizedProperty(val twins: Twins) @Test fun uppercasePropertyName() { - val adapter = moshi.adapter(UppercasePropertyName::class.java) + val adapter = moshi.adapter() val instance = adapter.fromJson("""{"AAA":1,"BBB":2}""")!! assertThat(instance.AAA).isEqualTo(1) @@ -1031,7 +1033,7 @@ class GeneratedAdaptersTest { /** https://github.com/square/moshi/issues/574 */ @Test fun mutableUppercasePropertyName() { - val adapter = moshi.adapter(MutableUppercasePropertyName::class.java) + val adapter = moshi.adapter() val instance = adapter.fromJson("""{"AAA":1,"BBB":2}""")!! assertThat(instance.AAA).isEqualTo(1) @@ -1085,7 +1087,7 @@ class GeneratedAdaptersTest { null }) .build() - val adapter = moshi.adapter(HasNullableBoolean::class.java).serializeNulls() + val adapter = moshi.adapter().serializeNulls() assertThat(adapter.fromJson("""{"boolean":"not a boolean"}""")) .isEqualTo(HasNullableBoolean(null)) assertThat(adapter.toJson(HasNullableBoolean(null))).isEqualTo("""{"boolean":null}""") @@ -1093,7 +1095,7 @@ class GeneratedAdaptersTest { @Test fun adaptersAreNullSafe() { val moshi = Moshi.Builder().build() - val adapter = moshi.adapter(HasNonNullConstructorParameter::class.java) + val adapter = moshi.adapter() assertThat(adapter.fromJson("null")).isNull() assertThat(adapter.toJson(null)).isEqualTo("null") } @@ -1115,12 +1117,12 @@ class GeneratedAdaptersTest { .build() val hasNonNullConstructorParameterAdapter = - moshi.adapter(HasNonNullConstructorParameter::class.java) + moshi.adapter() assertThat(hasNonNullConstructorParameterAdapter .fromJson("{\"a\":null}")).isEqualTo(HasNonNullConstructorParameter("fallback")) val hasNullableConstructorParameterAdapter = - moshi.adapter(HasNullableConstructorParameter::class.java) + moshi.adapter() assertThat(hasNullableConstructorParameterAdapter .fromJson("{\"a\":null}")).isEqualTo(HasNullableConstructorParameter("fallback")) assertThat(hasNullableConstructorParameterAdapter @@ -1132,7 +1134,7 @@ class GeneratedAdaptersTest { @Test fun delegatesToInstalledAdaptersBeforeNullCheckingWithGeneratedAdapter() { val moshi = Moshi.Builder().build() - val adapter = moshi.adapter(HasNullableTypeWithGeneratedAdapter::class.java) + val adapter = moshi.adapter() val encoded = HasNullableTypeWithGeneratedAdapter(null) assertThat(adapter.toJson(encoded)).isEqualTo("""{}""") @@ -1147,7 +1149,7 @@ class GeneratedAdaptersTest { @Test fun hasCollectionOfPrimitives() { val moshi = Moshi.Builder().build() - val adapter = moshi.adapter(HasCollectionOfPrimitives::class.java) + val adapter = moshi.adapter() val encoded = HasCollectionOfPrimitives(listOf(1, 2, -3)) assertThat(adapter.toJson(encoded)).isEqualTo("""{"listOfInts":[1,2,-3]}""") @@ -1161,7 +1163,7 @@ class GeneratedAdaptersTest { @Test fun customGenerator_withClassPresent() { val moshi = Moshi.Builder().build() - val adapter = moshi.adapter(CustomGeneratedClass::class.java) + val adapter = moshi.adapter() val unwrapped = (adapter as NullSafeJsonAdapter).delegate() assertThat(unwrapped).isInstanceOf(GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter::class.java) } @@ -1172,7 +1174,7 @@ class GeneratedAdaptersTest { @Test fun customGenerator_withClassMissing() { val moshi = Moshi.Builder().build() try { - moshi.adapter(CustomGeneratedClassMissing::class.java) + moshi.adapter() fail() } catch (e: RuntimeException) { assertThat(e).hasMessageContaining("Failed to find the generated JsonAdapter 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 6d2c1ea..18ce283 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 @@ -40,7 +40,7 @@ import kotlin.annotation.AnnotationRetention.RUNTIME class KotlinJsonAdapterTest { @Test fun constructorParameters() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -54,7 +54,7 @@ class KotlinJsonAdapterTest { @Test fun properties() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(Properties::class.java) + val jsonAdapter = moshi.adapter() val encoded = Properties() encoded.a = 3 @@ -73,7 +73,7 @@ class KotlinJsonAdapterTest { @Test fun constructorParametersAndProperties() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ConstructorParametersAndProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParametersAndProperties(3) encoded.b = 5 @@ -90,7 +90,7 @@ class KotlinJsonAdapterTest { @Test fun immutableConstructorParameters() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ImmutableConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = ImmutableConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -104,7 +104,7 @@ class KotlinJsonAdapterTest { @Test fun immutableProperties() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ImmutableProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = ImmutableProperties(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -121,7 +121,7 @@ class KotlinJsonAdapterTest { @Test fun constructorDefaults() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ConstructorDefaultValues::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorDefaultValues(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -135,7 +135,7 @@ class KotlinJsonAdapterTest { @Test fun requiredValueAbsent() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(RequiredValueAbsent::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4}""") @@ -149,7 +149,7 @@ class KotlinJsonAdapterTest { @Test fun nonNullConstructorParameterCalledWithNullFailsWithJsonDataException() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":null}") @@ -163,7 +163,7 @@ class KotlinJsonAdapterTest { val moshi = Moshi.Builder().add(object { @FromJson fun fromJson(string: String): String? = null }).add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":\"hello\"}") @@ -179,7 +179,7 @@ class KotlinJsonAdapterTest { @Test fun nonNullPropertySetToNullFailsWithJsonDataException() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":null}") @@ -193,7 +193,7 @@ class KotlinJsonAdapterTest { val moshi = Moshi.Builder().add(object { @FromJson fun fromJson(string: String): String? = null }).add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("{\"a\":\"hello\"}") @@ -209,7 +209,7 @@ class KotlinJsonAdapterTest { @Test fun duplicatedValueParameter() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(DuplicateValueParameter::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4,"a":4}""") @@ -223,7 +223,7 @@ class KotlinJsonAdapterTest { @Test fun duplicatedValueProperty() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(DuplicateValueProperty::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4,"a":4}""") @@ -240,7 +240,7 @@ class KotlinJsonAdapterTest { @Test fun explicitNull() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ExplicitNull::class.java) + val jsonAdapter = moshi.adapter() val encoded = ExplicitNull(null, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""") @@ -255,7 +255,7 @@ class KotlinJsonAdapterTest { @Test fun absentNull() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(AbsentNull::class.java) + val jsonAdapter = moshi.adapter() val encoded = AbsentNull(null, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""") @@ -270,7 +270,7 @@ class KotlinJsonAdapterTest { @Test fun repeatedValue() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(RepeatedValue::class.java) + val jsonAdapter = moshi.adapter() try { jsonAdapter.fromJson("""{"a":4,"b":null,"b":6}""") @@ -287,7 +287,7 @@ class KotlinJsonAdapterTest { .add(KotlinJsonAdapterFactory()) .add(UppercaseJsonAdapter()) .build() - val jsonAdapter = moshi.adapter(ConstructorParameterWithQualifier::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParameterWithQualifier("Android", "Banana") assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":"ANDROID","b":"Banana"}""") @@ -304,7 +304,7 @@ class KotlinJsonAdapterTest { .add(KotlinJsonAdapterFactory()) .add(UppercaseJsonAdapter()) .build() - val jsonAdapter = moshi.adapter(PropertyWithQualifier::class.java) + val jsonAdapter = moshi.adapter() val encoded = PropertyWithQualifier() encoded.a = "Android" @@ -323,7 +323,7 @@ class KotlinJsonAdapterTest { @Test fun constructorParameterWithJsonName() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ConstructorParameterWithJsonName::class.java) + val jsonAdapter = moshi.adapter() val encoded = ConstructorParameterWithJsonName(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"key a":3,"b":5}""") @@ -337,7 +337,7 @@ class KotlinJsonAdapterTest { @Test fun propertyWithJsonName() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(PropertyWithJsonName::class.java) + val jsonAdapter = moshi.adapter() val encoded = PropertyWithJsonName() encoded.a = 3 @@ -356,7 +356,7 @@ class KotlinJsonAdapterTest { @Test fun transientConstructorParameter() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(TransientConstructorParameter::class.java) + val jsonAdapter = moshi.adapter() val encoded = TransientConstructorParameter(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"b":5}""") @@ -371,7 +371,7 @@ class KotlinJsonAdapterTest { @Test fun requiredTransientConstructorParameterFails() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(RequiredTransientConstructorParameter::class.java) + moshi.adapter() fail() } catch (expected: IllegalArgumentException) { assertThat(expected).hasMessage("No default value for transient constructor parameter #0 " + @@ -384,7 +384,7 @@ class KotlinJsonAdapterTest { @Test fun transientProperty() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(TransientProperty::class.java) + val jsonAdapter = moshi.adapter() val encoded = TransientProperty() encoded.a = 3 @@ -413,7 +413,7 @@ class KotlinJsonAdapterTest { @Test fun constructorParametersAndPropertiesWithSameNamesMustHaveSameTypes() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(ConstructorParameterWithSameNameAsPropertyButDifferentType::class.java) + moshi.adapter() fail() } catch (expected: IllegalArgumentException) { assertThat(expected).hasMessage("'a' has a constructor parameter of type " + @@ -427,7 +427,7 @@ class KotlinJsonAdapterTest { @Test fun supertypeConstructorParameters() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(SubtypeConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = SubtypeConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -443,7 +443,7 @@ class KotlinJsonAdapterTest { @Test fun supertypeProperties() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(SubtypeProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = SubtypeProperties() encoded.a = 3 @@ -465,7 +465,7 @@ class KotlinJsonAdapterTest { @Test fun extendsPlatformClassWithPrivateField() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ExtendsPlatformClassWithPrivateField::class.java) + val jsonAdapter = moshi.adapter() val encoded = ExtendsPlatformClassWithPrivateField(3) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3}""") @@ -479,7 +479,7 @@ class KotlinJsonAdapterTest { @Test fun extendsPlatformClassWithProtectedField() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ExtendsPlatformClassWithProtectedField::class.java) + val jsonAdapter = moshi.adapter() val encoded = ExtendsPlatformClassWithProtectedField(3) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"buf":[0,0],"count":0}""") @@ -498,17 +498,17 @@ class KotlinJsonAdapterTest { @Test fun platformTypeThrows() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(Triple::class.java) + moshi.adapter>() fail() } catch (e: IllegalArgumentException) { assertThat(e).hasMessage( - "Platform class kotlin.Triple requires explicit JsonAdapter to be registered") + "Platform class kotlin.Triple in kotlin.Triple requires explicit JsonAdapter to be registered") } } @Test fun privateConstructorParameters() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(PrivateConstructorParameters::class.java) + val jsonAdapter = moshi.adapter() val encoded = PrivateConstructorParameters(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -525,7 +525,7 @@ class KotlinJsonAdapterTest { @Test fun privateConstructor() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(PrivateConstructor::class.java) + val jsonAdapter = moshi.adapter() val encoded = PrivateConstructor.newInstance(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -545,7 +545,7 @@ class KotlinJsonAdapterTest { @Test fun privateProperties() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(PrivateProperties::class.java) + val jsonAdapter = moshi.adapter() val encoded = PrivateProperties() encoded.a(3) @@ -576,7 +576,7 @@ class KotlinJsonAdapterTest { @Test fun unsettablePropertyIgnored() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(UnsettableProperty::class.java) + val jsonAdapter = moshi.adapter() val encoded = UnsettableProperty() encoded.b = 5 @@ -594,7 +594,7 @@ class KotlinJsonAdapterTest { @Test fun getterOnlyNoBackingField() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(GetterOnly::class.java) + val jsonAdapter = moshi.adapter() val encoded = GetterOnly(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5}""") @@ -612,7 +612,7 @@ class KotlinJsonAdapterTest { @Test fun getterAndSetterNoBackingField() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(GetterAndSetter::class.java) + val jsonAdapter = moshi.adapter() val encoded = GetterAndSetter(3, 5) assertThat(jsonAdapter.toJson(encoded)).isEqualTo("""{"a":3,"b":5,"total":8}""") @@ -641,7 +641,7 @@ class KotlinJsonAdapterTest { @Test fun nonPropertyConstructorParameter() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(NonPropertyConstructorParameter::class.java) + moshi.adapter() fail() } catch(expected: IllegalArgumentException) { assertThat(expected).hasMessage( @@ -654,7 +654,7 @@ class KotlinJsonAdapterTest { @Test fun kotlinEnumsAreNotCovered() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val adapter = moshi.adapter(UsingEnum::class.java) + val adapter = moshi.adapter() assertThat(adapter.fromJson("""{"e": "A"}""")).isEqualTo(UsingEnum(KotlinEnum.A)) } @@ -668,7 +668,7 @@ class KotlinJsonAdapterTest { @Test fun interfacesNotSupported() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(Interface::class.java) + moshi.adapter() fail() } catch (e: IllegalArgumentException) { assertThat(e).hasMessage("No JsonAdapter for interface " + @@ -681,7 +681,7 @@ class KotlinJsonAdapterTest { @Test fun abstractClassesNotSupported() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(AbstractClass::class.java) + moshi.adapter() fail() } catch (e: IllegalArgumentException) { assertThat(e).hasMessage("Cannot serialize abstract class " + @@ -694,7 +694,7 @@ class KotlinJsonAdapterTest { @Test fun innerClassesNotSupported() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(InnerClass::class.java) + moshi.adapter() fail() } catch (e: IllegalArgumentException) { assertThat(e).hasMessage("Cannot serialize inner class " + @@ -708,7 +708,7 @@ class KotlinJsonAdapterTest { class LocalClass(val a: Int) val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(LocalClass::class.java) + moshi.adapter() fail() } catch (e: IllegalArgumentException) { assertThat(e).hasMessage("Cannot serialize local class or object expression " + @@ -719,7 +719,7 @@ class KotlinJsonAdapterTest { @Test fun objectDeclarationsNotSupported() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() try { - moshi.adapter(ObjectDeclaration.javaClass) + moshi.adapter() fail() } catch (e: IllegalArgumentException) { assertThat(e).hasMessage("Cannot serialize object declaration " + @@ -748,7 +748,7 @@ class KotlinJsonAdapterTest { @Test fun manyProperties32() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ManyProperties32::class.java) + val jsonAdapter = moshi.adapter() val encoded = ManyProperties32( 101, 102, 103, 104, 105, @@ -788,7 +788,7 @@ class KotlinJsonAdapterTest { @Test fun manyProperties33() { val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - val jsonAdapter = moshi.adapter(ManyProperties33::class.java) + val jsonAdapter = moshi.adapter() val encoded = ManyProperties33( 101, 102, 103, 104, 105, @@ -892,12 +892,12 @@ class KotlinJsonAdapterTest { .add(KotlinJsonAdapterFactory()) .build() - assertThat(moshi.adapter(HasNonNullConstructorParameter::class.java) + assertThat(moshi.adapter() .fromJson("{\"a\":null}")).isEqualTo(HasNonNullConstructorParameter("fallback")) - assertThat(moshi.adapter(HasNullableConstructorParameter::class.java) + assertThat(moshi.adapter() .fromJson("{\"a\":null}")).isEqualTo(HasNullableConstructorParameter("fallback")) - assertThat(moshi.adapter(HasNullableConstructorParameter::class.java) + assertThat(moshi.adapter() .toJson(HasNullableConstructorParameter(null))).isEqualTo("{\"a\":\"fallback\"}") } @@ -905,8 +905,8 @@ class KotlinJsonAdapterTest { val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() - val generatedAdapter = moshi.adapter(UsesGeneratedAdapter::class.java) - val reflectionAdapter = moshi.adapter(UsesReflectionAdapter::class.java) + val generatedAdapter = moshi.adapter() + val reflectionAdapter = moshi.adapter() assertThat(generatedAdapter.toString()) .isEqualTo("GeneratedJsonAdapter(KotlinJsonAdapterTest.UsesGeneratedAdapter).nullSafe()") @@ -958,7 +958,7 @@ class KotlinJsonAdapterTest { }) .add(KotlinJsonAdapterFactory()) .build() - val adapter = moshi.adapter(HasNullableBoolean::class.java).serializeNulls() + val adapter = moshi.adapter().serializeNulls() assertThat(adapter.fromJson("""{"boolean":"not a boolean"}""")) .isEqualTo(HasNullableBoolean(null)) assertThat(adapter.toJson(HasNullableBoolean(null))).isEqualTo("""{"boolean":null}""") @@ -968,7 +968,9 @@ class KotlinJsonAdapterTest { val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() - val adapter = moshi.adapter(HasNonNullConstructorParameter::class.java) + + // TODO in CR: We had to mark this as nullable, vs before the jsonadapter factory would always run + val adapter = moshi.adapter() assertThat(adapter.fromJson("null")).isNull() assertThat(adapter.toJson(null)).isEqualTo("null") } @@ -976,7 +978,7 @@ class KotlinJsonAdapterTest { @Test fun kotlinClassesWithoutAdapterAreRefused() { val moshi = Moshi.Builder().build() try { - moshi.adapter(PlainKotlinClass::class.java) + moshi.adapter() fail("Should not pass here") } catch (e: IllegalArgumentException) { assertThat(e).hasMessageContaining("Reflective serialization of Kotlin classes") diff --git a/moshi/src/main/java/com/squareup/moshi/JsonAdapter.java b/moshi/src/main/java/com/squareup/moshi/JsonAdapter.java index 1bb63c9..9143b16 100644 --- a/moshi/src/main/java/com/squareup/moshi/JsonAdapter.java +++ b/moshi/src/main/java/com/squareup/moshi/JsonAdapter.java @@ -15,6 +15,7 @@ */ package com.squareup.moshi; +import com.squareup.moshi.internal.NonNullJsonAdapter; import com.squareup.moshi.internal.NullSafeJsonAdapter; import java.io.IOException; import java.lang.annotation.Annotation; @@ -140,29 +141,7 @@ public abstract class JsonAdapter { * handled elsewhere. This should only be used to fail on explicit nulls. */ @CheckReturnValue public final JsonAdapter nonNull() { - final JsonAdapter delegate = this; - return new JsonAdapter() { - @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()"; - } - }; + return new NonNullJsonAdapter<>(this); } /** Returns a JSON adapter equal to this, but is lenient when reading and writing. */ diff --git a/moshi/src/main/java/com/squareup/moshi/internal/NonNullJsonAdapter.java b/moshi/src/main/java/com/squareup/moshi/internal/NonNullJsonAdapter.java new file mode 100644 index 0000000..2708c4a --- /dev/null +++ b/moshi/src/main/java/com/squareup/moshi/internal/NonNullJsonAdapter.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 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.internal; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonDataException; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.JsonWriter; +import java.io.IOException; +import javax.annotation.Nullable; + +public final class NonNullJsonAdapter extends JsonAdapter { + + private final JsonAdapter delegate; + + public NonNullJsonAdapter(JsonAdapter delegate) { + this.delegate = delegate; + } + + public JsonAdapter delegate() { + return delegate; + } + + @Nullable + @Override + public 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 + public String toString() { + return delegate + ".nonNull()"; + } +} diff --git a/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java b/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java index 598e892..590e283 100644 --- a/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java +++ b/moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java @@ -282,7 +282,7 @@ public final class JsonAdapterTest { @Override public void toJson(JsonWriter writer, @Nullable Boolean value) throws IOException { throw new AssertionError(); } - }.lenient().nonNull(); + }.lenient().serializeNulls(); assertThat(adapter.fromJson("true true")).isEqualTo(true); } }