Today I was looking for this thing as my class had java.time.Instant
and the default gson could not deserialize it. My POJOs look like this:
open class RewardResult(
@SerializedName("id")
var id: Int,
@SerializedName("title")
var title: String?,
@SerializedName("details")
var details: String?,
@SerializedName("image")
var image: String?,
@SerializedName("start_time")
var startTimeUtcZulu: Instant?, // Unit: Utc / Zulu. Unit is very important
@SerializedName("end_time")
var endTimeUtcZulu: Instant?,
@SerializedName("unlock_expiry")
var unlockExpiryTimeUtcZulu: Instant?,
@SerializedName("target")
var target: Int,
@SerializedName("reward")
var rewardItem: RewardItem
);
data class RewardItem(
@SerializedName("type")
var type: String?,
@SerializedName("item_id")
var itemId: Int,
@SerializedName("amount")
var amount: Int
)
Then for Instant
variables, I parse the json's time variables and convert string to Instant. For integer , string, etc I use jsonObject.get("id").asInt
etc. For other pojo, I use the default deserializer like this:
val rewardItem: RewardItem = context!!.deserialize(rewardJsonElement,
RewardItem::class.java);
So the corresponding custom deserializer looks like this:
val customDeserializer: JsonDeserializer<RewardResult> = object : JsonDeserializer<RewardResult> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): RewardResult {
val jsonObject: JsonObject = json!!.asJsonObject;
val startTimeString: String? = jsonObject.get("start_time")?.asString;
var startTimeUtcZulu: Instant? = createTimeInstant(startTimeString);
val endTimeString: String? = jsonObject.get("end_time")?.asString;
var endTimeUtcZulu: Instant? = createTimeInstant(endTimeString);
val unlockExpiryStr: String? = jsonObject.get("unlock_expiry")?.asString;
var unlockExpiryUtcZulu: Instant? = createTimeInstant(unlockExpiryStr);
val rewardJsonElement: JsonElement = jsonObject.get("reward");
val rewardItem: ridmik.one.modal.reward.RewardItem = context!!.deserialize(rewardJsonElement,
ridmik.one.modal.reward.RewardItem::class.java); // I suppose this line means use the default jsonDeserializer
var output: ridmik.one.modal.reward.RewardResult = ridmik.one.modal.reward.RewardResult(
id = jsonObject.get("id").asInt,
title = jsonObject.get("title")?.asString,
details = jsonObject.get("details")?.asString,
image = jsonObject.get("image")?.asString,
startTimeUtcZulu = startTimeUtcZulu,
endTimeUtcZulu = endTimeUtcZulu,
unlockExpiryTimeUtcZulu = unlockExpiryUtcZulu,
target = jsonObject.get("target").asInt,
rewardItem = rewardItem
);
Timber.tag(TAG).e("output = "+output);
return output;
}
}
Finally, I create my custom gson like this:
val gsonBuilder = GsonBuilder();
gsonBuilder.registerTypeAdapter(RewardResult::class.javaObjectType,
this.customJsonDeserializer);
val customGson: Gson = gsonBuilder.create();