Hey guys!
I have this issue Failed to find the generated JsonAdapter constructor on one of my project.
If you have a look into build/generated/source/kapt I can't find the generated Adapters
sample project to reproduce this issue:
https://github.com/NodensN/issue-codegen-moshi
Launch test ApiErrorOperatorTest
--> https://github.com/NodensN/issue-codegen-moshi/blob/master/core/src/test/java/io/gmas/issuecodegenmoshi/core/ApiErrorOperatorTest.kt
stacktrace:
java.lang.RuntimeException: Failed to find the generated JsonAdapter constructor for class io.gmas.issuecodegenmoshi.core.network.envelopes.ErrorEnvelope
at com.squareup.moshi.StandardJsonAdapters.generatedAdapter(StandardJsonAdapters.java:252)
at com.squareup.moshi.StandardJsonAdapters$1.create(StandardJsonAdapters.java:62)
at com.squareup.moshi.Moshi.adapter(Moshi.java:130)
at com.squareup.moshi.Moshi.adapter(Moshi.java:64)
at io.gmas.issuecodegenmoshi.core.libs.rx.operators.ApiErrorOperator$apply$1.onNext(ApiErrorOperator.kt:35)
at io.gmas.issuecodegenmoshi.core.libs.rx.operators.ApiErrorOperator$apply$1.onNext(ApiErrorOperator.kt:21)
at io.reactivex.subjects.PublishSubject$PublishDisposable.onNext(PublishSubject.java:311)
at io.reactivex.subjects.PublishSubject.onNext(PublishSubject.java:231)
at io.gmas.issuecodegenmoshi.core.ApiErrorOperatorTest.testErrorResponse(ApiErrorOperatorTest.kt:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.NoSuchMethodException: io.gmas.issuecodegenmoshi.core.network.envelopes.ErrorEnvelopeJsonAdapter.<init>(com.squareup.moshi.Moshi, [Ljava.lang.reflect.Type;)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at com.squareup.moshi.StandardJsonAdapters.generatedAdapter(StandardJsonAdapters.java:239)
... 36 more
any ideas?
Thanks for the careful report. Something is broken; it looks like we're seeing the class but not its constructor.
I fixed this issue, it was a mistake on my side (usual haha).
Here is the mistake:
I was using Types.newParameterizedType(#1) -> here, to parse the json like this:
val type = Types.newParameterizedType(ErrorEnvelope::class.java)
val adapter = moshi.adapter<ErrorEnvelope>(type)
val envelope = adapter.fromJson(response.errorBody()?.string())
but my ErrorEnvelope here was annotated by @JsonClass(generateAdapter = true) to use the feature kotlin codegen
@JsonClass(generateAdapter = true)
data class ErrorEnvelope(
@Json(name = "error") val error: String? = null,
@Json(name = "code") val code: Int? = null
)
Then I removed the Types.newParameterizedType(#1) to use the adapter on its simple way:
val adapter = moshi.adapter(ErrorEnvelope::class.java)
val envelope = adapter.fromJson(response.errorBody()?.string())
Everything is working fine now!
I am having similar issue, only with proguard enabled. I am using moshi.adapter(Types.newParameterizedType(List::class.java, MyClass::class.java)). Looks like I am missing a proguard rule, but cannot figure out what is needed.
Using moshi.adapter(MyClass::class.java) works ok with proguard when I don't need a list, but have to use Types.newParameterizedType to get an adapter for a list of items.
Hey @okaymak, I am also facing the same issue. Did you find a workaround around this??
Moshi Version: 1.9.2
-dontwarn org.jetbrains.annotations.**
-keep class kotlin.Metadata { *; }
-keepclassmembers class com.myapp.packagnename.** {
<init>(...);
<fields>;}
-keep @android.support.annotation.Keep class * {*;}
Change com.myapp.packagnename to your package-name
@PramodGarg I know this is an old issue but I ran into this problem as well on Moshi 1.9.2 and found a solution:
In my case I have a generic class for responses:
@JsonClass(generateAdapter = true)
data class Response<out T>(val data: T? = null, val errors: List<Error> = listOf())
The generated constructor for the JsonAdapter has the signature ResponseJsonAdapter<T>(moshi: Moshi, types: Array<Type>). When Moshi tries to find this adapter it will need to invoke this constructor with both Moshi and the types parameters. In order to do that it needs to know that the Type for the class is parameterized (see the method generatedAdapter).
Suppose the data is of type UserData which has its own generated adapter, when getting the adapter and (de)serialize the object instead of using:
moshi.adapter<Reponse<UserData>>(Response::class.java) // <-- does not know about the parameter `T` in the Reponse
define a new parameterized type and get the adapter using that Type:
val parameterizedType = Types.newParameterizedType(Response::class.java, UserData::class.java)
moshi.adapter<Reponse<UserData>>(parameterizedType)
And you're all set! Hope this helps someone.
Most helpful comment
@PramodGarg I know this is an old issue but I ran into this problem as well on Moshi 1.9.2 and found a solution:
In my case I have a generic class for responses:
The generated constructor for the
JsonAdapterhas the signatureResponseJsonAdapter<T>(moshi: Moshi, types: Array<Type>). When Moshi tries to find this adapter it will need to invoke this constructor with bothMoshiand thetypesparameters. In order to do that it needs to know that theTypefor the class is parameterized (see the method generatedAdapter).Suppose the data is of type
UserDatawhich has its own generated adapter, when getting the adapter and (de)serialize the object instead of using:define a new parameterized type and get the adapter using that
Type:And you're all set! Hope this helps someone.