Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何为Gson编写自定义JSON反序列化程序?_Java_Json_Gson_Deserialization - Fatal编程技术网

Java 如何为Gson编写自定义JSON反序列化程序?

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

我有一个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"}]
我已尝试编写自定义反序列化程序:

@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
,提高可读性。有什么方法可以知道反序列化程序中当前正在处理的字段名吗?回答得很好……它完美地解决了我的问题……非常感谢:)