to share code, and to only apply the deserialization logic to specific fields:
JSON model:
public class AdminLoginResponse implements LoginResponse
{
public Login login;
public Customer customer;
@JsonAdapter(MultiOrganizationArrayOrObject.class) // <-------- look here
public RealmList<MultiOrganization> allAccounts;
}
field-specific class:
class MultiOrganizationArrayOrObject
: ArrayOrSingleObjectTypeAdapter<RealmList<MultiOrganization>,MultiOrganization>(kClass()) {
override fun List<MultiOrganization>.toTypedList() = RealmList(*this.toTypedArray())
}
abstract class:
/**
* parsed field can either be a [JSONArray] of type [Element], or an single [Element] [JSONObject].
*/
abstract class ArrayOrSingleObjectTypeAdapter<TypedList: List<Element>, Element : Any>(
private val elementKClass: KClass<Element>
) : JsonDeserializer<TypedList> {
override fun deserialize(
json: JsonElement, typeOfT: Type?, ctx: JsonDeserializationContext
): TypedList = when {
json.isJsonArray -> json.asJsonArray.map { ctx.deserialize<Element>(it, elementKClass.java) }
json.isJsonObject -> listOf(ctx.deserialize<Element>(json, elementKClass.java))
else -> throw RuntimeException("Unexpected JSON type: " + json.javaClass)
}.toTypedList()
abstract fun List<Element>.toTypedList(): TypedList
}