[英]How do I write a custom JSON deserializer for Gson?
I have a Java class, User:我有一个 Java 类,用户:
public class User
{
int id;
String name;
Timestamp updateDate;
}
And I receive a JSON list containing user objects from a webservice:我收到一个包含来自网络服务的用户对象的 JSON 列表:
[{"id":1,"name":"Jonas","update_date":"1300962900226"},
{"id":5,"name":"Test","date_date":"1304782298024"}]
I have tried to write a custom deserializer:我试图编写一个自定义反序列化器:
@Override
public User deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
return new User(
json.getAsJsonPrimitive().getAsInt(),
json.getAsString(),
json.getAsInt(),
(Timestamp)context.deserialize(json.getAsJsonPrimitive(),
Timestamp.class));
}
But my deserializer doesn't work.但是我的解串器不起作用。 How can I write a custom JSON deserializer for Gson?
如何为 Gson 编写自定义 JSON 反序列化器?
I'd take a slightly different approach as follows, so as to minimize "manual" parsing in my code, as unnecessarily doing otherwise somewhat defeats the purpose of why I'd use an API like Gson in the first place.我将采用如下略有不同的方法,以最大程度地减少我的代码中的“手动”解析,因为不必要地这样做会在某种程度上违背我为什么首先使用像 Gson 这样的 API 的目的。
// output:
// [User: id=1, name=Jonas, updateDate=2011-03-24 03:35:00.226]
// [User: id=5, name=Test, updateDate=2011-05-07 08:31:38.024]
// using java.sql.Timestamp
public class Foo
{
static String jsonInput =
"[" +
"{\"id\":1,\"name\":\"Jonas\",\"update_date\":\"1300962900226\"}," +
"{\"id\":5,\"name\":\"Test\",\"update_date\":\"1304782298024\"}" +
"]";
public static void main(String[] args)
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
gsonBuilder.registerTypeAdapter(Timestamp.class, new TimestampDeserializer());
Gson gson = gsonBuilder.create();
User[] users = gson.fromJson(jsonInput, User[].class);
for (User user : users)
{
System.out.println(user);
}
}
}
class User
{
int id;
String name;
Timestamp updateDate;
@Override
public String toString()
{
return String.format(
"[User: id=%1$d, name=%2$s, updateDate=%3$s]",
id, name, updateDate);
}
}
class TimestampDeserializer implements JsonDeserializer<Timestamp>
{
@Override
public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
long time = Long.parseLong(json.getAsString());
return new Timestamp(time);
}
}
(This assumes that "date_date" should be "update_date", in the original question.) (这假设原始问题中的“date_date”应该是“update_date”。)
@Override
public User deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jobject = json.getAsJsonObject();
return new User(
jobject.get("id").getAsInt(),
jobject.get("name").getAsString(),
new Timestamp(jobject.get("update_date").getAsLong()));
}
I'm assuming User class has the appropriate constructor.我假设 User 类具有适当的构造函数。
Today I was looking for this thing as my class had java.time.Instant
and the default gson could not deserialize it.今天我正在寻找这个东西,因为我的班级有
java.time.Instant
并且默认的 gson 无法反序列化它。 My POJOs look like this:我的 POJO 如下所示:
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.然后对于
Instant
变量,我解析 json 的时间变量并将字符串转换为 Instant。 For integer , string, etc I use jsonObject.get("id").asInt
etc. For other pojo, I use the default deserializer like this:对于 integer 、 string 等,我使用
jsonObject.get("id").asInt
等。对于其他 pojo,我使用默认的反序列化器,如下所示:
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:最后,我像这样创建我的自定义 gson:
val gsonBuilder = GsonBuilder();
gsonBuilder.registerTypeAdapter(RewardResult::class.javaObjectType,
this.customJsonDeserializer);
val customGson: Gson = gsonBuilder.create();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.