I have a simple response from my api, something that starts with a JSONArray and inside each item of the array some properties are also arrays, something like this
[
{
"regularProp": 123,
"anotherThing": "hello",
"listOfThings": [
{"blahblah": 123}
]
}
]
now I have modeled my data like this
data class ArrayResponse(
val regularProp: Int,
val anotherThing: String,
val listOfThings: ArrayList<Thing>
)
data class Thing(
val blahblah: Int
)
then based on the documentation I have a Adapter because is necesary in order to parse JSONArray responses with moshi, I wrote a JsonListAdapterFactory because I have more that one ArrayList
class MoshiJsonListAdapersFactory : JsonAdapter.Factory {
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
return when (type) {
Types.newParameterizedType(ArrayList::class.java, AResponse::class.java) ->
moshi.adapter<ArrayList<AResponse>>(type)
Types.newParameterizedType(ArrayList::class.java, ArrayResponse::class.java) ->
moshi.adapter<ArrayList<ArrayResponse>>(type)
Types.newParameterizedType(ArrayList::class.java, Thing::class.java) ->
moshi.adapter<ArrayList<Thing>>(type)
else -> null
}
}
}
then I build my moshi adapter like this
Moshi.Builder()
.add(HexColorAdapter())
.add(AnotherFieldAdapter())
.add(MoshiJsonListAdapersFactory())
.add(KotlinJsonAdapterFactory())
.build()
then problem comes when I try to parse the JSON described above, I got an StackOverflowError and a thousand of com.squareup.moshi.Moshi$DeferredAdapter.fromJson(Moshi.java:234), any clue how to solve this :/
I have replaced the moshi.adapter<ArrayList<Thing>>(type) by my own JsonAdapter<List<T>> and works, but it seems like something that it should work out the box
Moshi supports List by default only. Concrete types like ArrayList, LinkedList, and Vector are not supported. This is deliberate: if you need a specific collection implementation you can hook it up yourself.
The easiest way to handle ArrayList is with @ToJson and @FromJson . The methods should just map from one to the other.
@ToJson fun arrayListToJson(list: ArrayList<Thing>) : List<Thing> = list
@FromJson fun arrayListFromJson(list: List<Thing>) : ArrayList<Thing> = ArrayList(list)
The above is true.
Also, the reason for the StackOverflow error specifically here is that you have moshi.adapter when you meant moshi.nextAdapter. Otherwise, you'll keep calling into your own factory when you want to skip past it.
(also, nitpick: consider using Types.equals instead of the equals check that when does.)
i need to retrieve an object containing a map. doesnt seem to work with the codegen option set to true. not sure how to create an adapter? cant find tutorials out there with indepth explanation
@eoinahern Consider posting on Stack Overflow with the moshi tag and show what you have tried and want to accomplish. Somebody there might find time to help.
Those who searched "ArrayList moshi" in google:
https://stackoverflow.com/a/61272734/1064316
Most helpful comment
Moshi supports List by default only. Concrete types like ArrayList, LinkedList, and Vector are not supported. This is deliberate: if you need a specific collection implementation you can hook it up yourself.
The easiest way to handle ArrayList is with
@ToJsonand@FromJson. The methods should just map from one to the other.