Resolve generic property types in KotlinJsonAdapter.

This commit is contained in:
Eric Cochran 2018-04-03 17:37:38 -07:00
parent d045947ea7
commit dc450e6192
3 changed files with 52 additions and 3 deletions

View file

@ -225,8 +225,9 @@ class KotlinJsonAdapterFactory : JsonAdapter.Factory {
}
val name = jsonAnnotation?.name ?: property.name
val resolvedPropertyType = Types.resolve(type, rawType, property.returnType.javaType)
val adapter = moshi.adapter<Any>(
property.returnType.javaType, Util.jsonAnnotations(allAnnotations.toTypedArray()))
resolvedPropertyType, Util.jsonAnnotations(allAnnotations.toTypedArray()))
bindingsByName[property.name] =
KotlinJsonAdapter.Binding(name, adapter, property as KProperty1<Any, Any?>, parameter)

View file

@ -21,6 +21,7 @@ import com.squareup.moshi.JsonDataException
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import com.squareup.moshi.Types
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assert.fail
import org.junit.Test
@ -763,7 +764,53 @@ class KotlinJsonAdapterTest {
var v26: Int, var v27: Int, var v28: Int, var v29: Int, var v30: Int,
var v31: Int, var v32: Int, var v33: Int)
// TODO(jwilson): resolve generic types?
data class Box<out T>(val data: T)
@Test fun genericTypes() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val stringBoxAdapter = moshi.adapter<Box<String>>(
Types.newParameterizedTypeWithOwner(KotlinJsonAdapterTest::class.java, Box::class.java,
String::class.java))
assertThat(stringBoxAdapter.fromJson("""{"data":"hello"}""")).isEqualTo(Box("hello"))
assertThat(stringBoxAdapter.toJson(Box("hello"))).isEqualTo("""{"data":"hello"}""")
}
data class NestedGenerics<R, C, out V>(val value: Map<R, Map<C, List<V>>>)
@Test fun nestedGenericTypes() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val type = Types.newParameterizedTypeWithOwner(
KotlinJsonAdapterTest::class.java,
NestedGenerics::class.java,
String::class.java,
Int::class.javaObjectType,
Types.newParameterizedTypeWithOwner(
KotlinJsonAdapterTest::class.java,
Box::class.java,
String::class.java
)
)
val adapter = moshi.adapter<NestedGenerics<String, Int, Box<String>>>(type).indent(" ")
val json = """
|{
| "value": {
| "hello": {
| "1": [
| {
| "data": " "
| },
| {
| "data": "world!"
| }
| ]
| }
| }
|}
""".trimMargin()
val value = NestedGenerics(mapOf("hello" to mapOf(1 to listOf(Box(" "), Box("world!")))))
assertThat(adapter.fromJson(json)).isEqualTo(value)
assertThat(adapter.toJson(value)).isEqualTo(json)
}
@Retention(RUNTIME)
@JsonQualifier

View file

@ -373,7 +373,8 @@ public final class Types {
return new Type[] { Object.class, Object.class };
}
static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
@CheckReturnValue // TODO(eric): Move this to internal Utils.
public static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
// This implementation is made a little more complicated in an attempt to avoid object-creation.
while (true) {
if (toResolve instanceof TypeVariable) {