Java 如何为Gson编写自定义JSON反序列化程序?
我有一个Java类,用户:Java 如何为Gson编写自定义JSON反序列化程序?,java,json,gson,deserialization,Java,Json,Gson,Deserialization,我有一个Java类,用户: public class User { int id; String name; Timestamp updateDate; } 我从Web服务接收到一个JSON列表,其中包含用户对象: [{"id":1,"name":"Jonas","update_date":"1300962900226"}, {"id":5,"name":"Test","date_date":"1304782298024"}] 我已尝试编写自定义反序列化程序: @Ov
public class User
{
int id;
String name;
Timestamp updateDate;
}
我从Web服务接收到一个JSON列表,其中包含用户对象:
[{"id":1,"name":"Jonas","update_date":"1300962900226"},
{"id":5,"name":"Test","date_date":"1304782298024"}]
我已尝试编写自定义反序列化程序:
@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));
}
但是我的反序列化程序不工作。如何为Gson编写自定义JSON反序列化程序
@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()));
}
我假设用户类具有适当的构造函数。我将采用以下稍微不同的方法,以尽量减少代码中的“手动”解析,因为不必要地这样做会在某种程度上违背我为什么首先使用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);
}
}
//输出:
//[用户:id=1,name=Jonas,updateDate=2011-03-2403:35:00.226]
//[用户:id=5,name=Test,updateDate=2011-05-07 08:31:38.024]
//使用java.sql.Timestamp
公开课Foo
{
静态字符串jsonInput=
"[" +
“{\'id\':1,\'name\':\'Jonas\',\'update\'u date\':\'1300962900226\'”+
“{\'id\':5,\'name\':\'Test\',\'update\'u date\':\'1304782298024\'”+
"]";
公共静态void main(字符串[]args)
{
GsonBuilder GsonBuilder=新的GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_,带下划线);
gsonBuilder.registerTypeAdapter(Timestamp.class,新的TimestampDeserializer());
Gson-Gson=gsonBuilder.create();
User[]users=gson.fromJson(jsonInput,User[].class);
for(用户:用户)
{
System.out.println(用户);
}
}
}
类用户
{
int-id;
字符串名;
时间戳更新日期;
@凌驾
公共字符串toString()
{
返回字符串格式(
“[用户:id=%1$d,名称=%2$s,更新日期=%3$s]”,
id、名称、更新日期);
}
}
类时间戳反序列化器实现JsonDeserializer
{
@凌驾
公共时间戳反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)
抛出JsonParseException
{
long time=long.parseLong(json.getAsString());
返回新的时间戳(time);
}
}
(在原始问题中,假设“date\u date”应该是“update\u date”)今天我在寻找这个东西,因为我的类有
java.time.Instant
,默认的gson无法反序列化它。我的POJO看起来像这样:
开放类奖励结果(
@序列化名称(“id”)
变量id:Int,
@序列化名称(“标题”)
变量标题:字符串?,
@序列化名称(“详细信息”)
变量详细信息:字符串?,
@序列化名称(“图像”)
变量图像:字符串?,
@SerializedName(“开始时间”)
var startTimeUtcZulu:Instant?,//单位:Utc/Zulu。单位非常重要
@SerializedName(“结束时间”)
var endTimeUtcZulu:即时?,
@SerializedName(“解锁到期”)
var unlockExpiryTimeUtcZulu:即时?,
@SerializedName(“目标”)
var目标:Int,
@序列化名称(“奖励”)
var rewardItem:rewardItem
);
数据类重写(
@序列化名称(“类型”)
变量类型:字符串?,
@SerializedName(“项目id”)
var itemId:Int,
@序列化名称(“金额”)
风险值金额:整数
)
然后对于Instant
变量,我解析json的时间变量并将字符串转换为Instant。对于整数、字符串等,我使用jsonObject.get(“id”).asInt
等。对于其他pojo,我使用默认的反序列化程序,如下所示:
val-rewardItem:rewardItem=context!!。反序列化(rewardJsonElement,
RewardItem::class.java);
因此,相应的自定义反序列化程序如下所示:
val customDeserializer:JsonDeserializer=object:JsonDeserializer{
重写有趣的反序列化(json:JsonElement?、TypeSoft:Type?、context:JsonDeserializationContext?):RewardResult{
val-jsonObject:jsonObject=json!!.asJsonObject;
val startTimeString:String?=jsonObject.get(“开始时间”)?.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_expiration”)?.asString;
var unlockXPiryUtczulu:Instant?=createTimeInstant(unlockXPirystr);
val rewardJsonElement:JsonElement=jsonObject.get(“奖励”);
val rewardItem:ridmik.one.modal.reward.rewardItem=context,
ridmik.one.modal.reward.RewardItem::class.java);//我想这行的意思是使用默认的jsonDeserializer
var输出:ridmik.one.modal.raward.RewardResult=ridmik.one.modal.raward.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,
UnlockXPirytimeutCzulu=UnlockXPiryutCzulu,
target=jsonObject.get(“target”).asInt,
rewardItem=rewardItem
);
Timber.tag(tag.e)(“output=“+output”);
返回输出;
}
}
最后,我创建了自定义gson,如下所示:
val gsonBuilder=gsonBuilder();
gsonBuilder.registerTypeAdapter(RewardResult::class.javaObjectType,
这个.customJsonDeserializer);
val customGson:Gson=gsonBuilder.create();
这个例子有帮助吗?你说“不行”是什么意思?问题是什么?date_date应该是update_date吗?我当然更喜欢这个模型-如果时间戳是唯一无法解析的东西,那么最好让时间戳反序列化,而不是手动解析整个用户对象,而Gson已经完全能够这样做了。小编辑。我们可以使用“returnnewtimestamp(json.getAsLong());”而不是“long-time=long.parseLong(json.getAsString());returnnewtimestamp(time);”您还可以使用方法链来链接GsonBuilder
,提高可读性。有什么方法可以知道反序列化程序中当前正在处理的字段名吗?回答得很好……它完美地解决了我的问题……非常感谢:)