title: Unwrapping enveloped responses with Retrofit, Moshi, and Kotlin
body: <p>I'm working with an API that returns responses that look like:</p>
  
  <pre><code>{
    "irrelevantStuff": {},
    "data": [] 
  }
  </code></pre>
  
  <p>I'd like to follow the approach demonstrated in <a href="https://www.youtube.com/watch?v=t34AQlblSeE&amp;feature=youtu.be&amp;t=1685" rel="nofollow noreferrer">this presentation from Jake</a>, where he creates a Retrofit converter factory to handle and unwrap the envelope type. The only problem is that the approach shown uses Gson and Java, where as I'm trying to make use of Moshi and Kotlin.</p>
  
  <p>I've declared my envelope type as:</p>
  
  <pre><code>data class Envelope&lt;T&gt;(val data: T)
  </code></pre>
  
  <p>Any my converter factory as:</p>
  
  <pre><code>object EnvelopeConverter : Converter.Factory() {
  
    override fun responseBodyConverter(
        type: Type,
        annotations: Array&lt;Annotation&gt;,
        retrofit: Retrofit
    ): Converter&lt;ResponseBody, *&gt;? {
  
      val envelopedType = Types.newParameterizedType(Envelope::class.java, type)
      val delegate: Converter&lt;ResponseBody, Envelope&lt;Any&gt;&gt;? =
          retrofit.nextResponseBodyConverter(this, envelopedType, annotations)
  
      return Unwrapper(delegate)
    }
  
    private class Unwrapper&lt;T&gt;(
        private val delegate: Converter&lt;ResponseBody, Envelope&lt;T&gt;&gt;?
    ) : Converter&lt;ResponseBody, T&gt; {
  
      override fun convert(value: ResponseBody): T? {
        return delegate?.convert(value)?.data
      }
    }
  }
  </code></pre>
  
  <p>Retrofit has been configured as:</p>
  
  <pre><code>val retrofit: Retrofit = Retrofit.Builder()
      .baseUrl(currentEndpoint.url)
      .addConverterFactory(EnvelopeConverter)
      .addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(KotlinJsonAdapterFactory()).build()))
      .build()
  </code></pre>
  
  <p>However when a request is executed, I receive the exception shown below. It's worth noting that this converter <strong>works fine when using the <code>moshi-kotlin-codegen</code> dependency</strong>. It's just the <code>moshi-kotlin</code> reflection based library it has issues with. What's the cause of this?</p>
  
  <pre><code>java.lang.AssertionError: Built-in class kotlin.Any is not found
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns$3.invoke(KotlinBuiltIns.java:113)
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns$3.invoke(KotlinBuiltIns.java:108)
          at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:440)
          at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:515)
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getBuiltInClassByName(KotlinBuiltIns.java:362)
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getAny(KotlinBuiltIns.java:367)
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getAnyType(KotlinBuiltIns.java:642)
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getNullableAnyType(KotlinBuiltIns.java:647)
          at kotlin.reflect.jvm.internal.impl.builtins.KotlinBuiltIns.getDefaultBound(KotlinBuiltIns.java:652)
          at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedTypeParameterDescriptor.resolveUpperBounds(DeserializedTypeParameterDescriptor.kt:45)
          at kotlin.reflect.jvm.internal.impl.descriptors.impl.AbstractTypeParameterDescriptor$TypeParameterTypeConstructor.computeSupertypes(AbstractTypeParameterDescriptor.java:154)
          at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor$supertypes$1.invoke(AbstractTypeConstructor.kt:34)
          at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor$supertypes$1.invoke(AbstractTypeConstructor.kt:22)
          at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:346)
          at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:402)
          at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor.getSupertypes(AbstractTypeConstructor.kt:23)
          at kotlin.reflect.jvm.internal.impl.descriptors.impl.AbstractTypeParameterDescriptor.getUpperBounds(AbstractTypeParameterDescriptor.java:116)
          at kotlin.reflect.jvm.internal.impl.types.typeUtil.TypeUtilsKt.getRepresentativeUpperBound(TypeUtils.kt:237)
          at kotlin.reflect.jvm.internal.impl.resolve.jvm.InlineClassManglingRulesKt.isTypeParameterWithUpperBoundThatRequiresMangling(inlineClassManglingRules.kt:44)
          at kotlin.reflect.jvm.internal.impl.resolve.jvm.InlineClassManglingRulesKt.requiresFunctionNameMangling(inlineClassManglingRules.kt:37)
          at kotlin.reflect.jvm.internal.impl.resolve.jvm.InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters(inlineClassManglingRules.kt:23)
          at kotlin.reflect.jvm.internal.KFunctionImpl.createConstructorCaller(KFunctionImpl.kt:145)
          at kotlin.reflect.jvm.internal.KFunctionImpl.access$createConstructorCaller(KFunctionImpl.kt:36)
          at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:80)
          at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:36)
          at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:62)
          at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
          at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(Unknown Source:7)
          at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:62)
          at kotlin.reflect.jvm.KCallablesJvm.setAccessible(KCallablesJvm.kt:82)
          at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:221)
          at com.squareup.moshi.Moshi.adapter(Moshi.java:138)
          at com.squareup.moshi.Moshi.adapter(Moshi.java:98)
          at retrofit2.converter.moshi.MoshiConverterFactory.responseBodyConverter(MoshiConverterFactory.java:91)
          at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:352)
  E/AndroidRuntime:     at codes.chrishorner.socketweather.data.EnvelopeConverter.responseBodyConverter(EnvelopeConverter.kt:19)
          at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:352)
          at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:335)
          at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:113)
          at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:82)
          at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:37)
          at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:192)
          at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
          at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
          at $Proxy1.searchForLocation(Unknown Source)
          at codes.chrishorner.socketweather.MainActivity$onStart$1.invokeSuspend(MainActivity.kt:46)
          at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
          at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
          at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:561)
          at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:727)
          at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:667)
          at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:655)
  </code></pre>