[TL, DR] Here is a sample that reproduces the crash in a simple android app
Long Description
I have two polymorphic hierarchies of Vehicle and Tyre class like this
sealed class Vehicle {
abstract val model: String
abstract val type : String
abstract val tyres: List<Tyre>?
}
@JsonClass(generateAdapter = true)
data class Car(override val model: String,
override val type: String,
override val tyres: List<Tyre>?): Vehicle()
@JsonClass(generateAdapter = true)
data class Truck(override val model: String,
override val type: String,
override val tyres: List<Tyre>?): Vehicle()
sealed class Tyre {
abstract val type : String
}
@JsonClass(generateAdapter = true)
data class MRFTyre(override val type : String): Tyre()
@JsonClass(generateAdapter = true)
data class ApolloTyre(override val type : String): Tyre()
I am creating Moshi instance as follows
val moshi = Moshi.Builder()
// ... add your own JsonAdapters and factories ...
.add(
PolymorphicJsonAdapterFactory.of(Vehicle::class.java, "type")
.withSubtype(Car::class.java, "car")
.withSubtype(Truck::class.java, "truck")
)
.add(
PolymorphicJsonAdapterFactory.of(Tyre::class.java, "type")
.withSubtype(MRFTyre::class.java, "mrf")
.withSubtype(ApolloTyre::class.java, "apollo")
)
.add(SkipBadElementsListAdapter.Factory)
.build()
I am Using SkipBadElementsListAdapter from this stackoverflow answer And trying to deserialize this JSON
[
{
"model": "m1",
"type": "car",
"tyres": [
{
"type": "mrf"
},
{
"type": "apollo"
}
]
},
{
"model": "m2",
"type": "truck",
"tyres": [
{
"type": "mrf"
},
{
"type": "apollo"
},
{
"type": "apollo"
}
]
}
]
When I try to deserialize if Json I get followingIllegalArgumentException
java.lang.IllegalArgumentException: No JsonAdapter for E (with no annotations)
for E
for interface java.util.List
for class java.lang.Object
for class com.example.moshitest.Tyre
for java.util.List<com.example.moshitest.Tyre> tyres
for class com.example.moshitest.Car
for class com.example.moshitest.Vehicle
for java.util.List<com.example.moshitest.Vehicle>
...
...
I am not sure why its not able to find right JsonAdapter when using SkipBadElementsListAdapter. Strangely, it works fine when this adapter is not added to Moshi.Builder(). Let me know if I am doing something wrong here.
Upon investigating more I found that Tyres does not have to be a polymorphic list in order for crash to reproduce. Its crashing with even a simple list
following class hierarchy also reproduce the issue
sealed class Vehicle {
abstract val model: String
abstract val type : String
abstract val tyres: List<Tyre>?
}
@JsonClass(generateAdapter = true)
data class Car(override val model: String,
override val type: String,
override val tyres: List<Tyre>?): Vehicle()
@JsonClass(generateAdapter = true)
data class Truck(override val model: String,
override val type: String,
override val tyres: List<Tyre>?): Vehicle()
@JsonClass(generateAdapter = true)
data class Tyre(val type: String)
I have simplified the sample accordingly. Also I can confirm that in this setting both factories work individually fine just not together.
thanks so much for the repro case. We'll take a look soon 馃檹
Same problem here. Maybe someone can provide some suggestion for investigation?
SkipBadElementsListAdapter looks fine I think.
Sorry we slipped on this for 1.9.0. I'll take a look this week
@abhishekBansal I tried your example and it works fine for me. Example branch: https://github.com/square/moshi/tree/z/repro_865
@vararg do you have an actionable repro example?
@ZacSweers I can still reproduce this everytime on master branch of same repository with same library versions. This sample app crashes with provided crashstack on logcat upon launch. My test device is Google Pixel 3 running Android 10
Please try your sample project with the latest version (1.9.1)? I pulled the sample into the linked branch and it works fine on Moshi master. There have been a number of changes and there鈥檚 a chance your issue was maybe indirectly fixed along the way.
works fine in v1.9.1.
You may now close the issue.
Also if you can shed some light on what was the issue would be great. Thanks!
For a hint if I place this check in Factory. This issue does not re reproduce even in older version
if (type !is ParameterizedType) {
return null // No type parameter? This factory doesn't apply.
}
@ZacSweers Sorry can't provide more info right now, after lib update to 1.9.1 my sample blocked with new issue https://github.com/square/moshi/issues/990
Closing this out since @abhishekBansal's original issue is resolved. To be totally honest, so much has changed since 1.8 that I'm not certain why it works now. But, all's well that ends well?
@vararg please open a separate issue with concrete repro steps if you're still seeing this after 1.9.2
@vararg mind trying your issue against latest master? It has a fix for #990