web-dev-qa-db-ja.com

Gson:日付のJsonSyntaxException

Gsonを使用してjson配列を逆シリアル化しようとしていますが、現在JsonSyntaxExceptionが発生しています。 json文字列は、JsonResultを使用して.NET MVC3 Webサービスによって作成されました(つまり、手動でjsonを作成しているのではなく、他のいくつかのプラットフォームで動作することがわかっているライブラリによって作成されています)。

これはjsonです:

[{"PostID":1,"StudentID":39,"StudentName":"Joe Blow",
"Text":"Test message.","CreateDate":"\/Date(1350178408267)\/",
"ModDate":"\/Date(1350178408267)\/","CommentCount":0}]

これはコードです:

public class Post {
   public int PostID;
   public int StudentID;
   public String StudentName;
   public String Text;
   public Date CreateDate;
   public Date ModDate;

   public Post() { }
}

Type listOfPosts = new TypeToken<ArrayList<Post>>(){}.getType();
ArrayList<Post> posts = new Gson().fromJson(json, listOfPosts);

例外は、日付形式が無効であることを示しています。

com.google.gson.JsonSyntaxException: /Date(1350178408267)/

誰が何が起こっているのか知っていますか?

12
mtmurdock

私は答えを見つけました ここ しかし、もっと簡単な方法がないのは奇妙だと思いました。私が使用した他のいくつかのjsonライブラリは、.NETjson形式をネイティブにサポートしています。 Gsonがそれを処理しなかったとき私は驚いた。より良い方法があるに違いありません。誰かが知っているなら、ここに投稿してください。それでも、これが私の解決策でした。

カスタムJsonDeserializerを作成し、それをDate型に登録しました。そうすることで、Gsonはデフォルトの代わりにDateタイプに私のデシリアライザーを使用します。カスタムの方法でシリアル化/逆シリアル化する場合は、他のタイプでも同じことができます。

public class JsonDateDeserializer implements JsonDeserializer<Date> {
   public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
      String s = json.getAsJsonPrimitive().getAsString();
      long l = Long.parseLong(s.substring(6, s.length() - 2));
      Date d = new Date(l);
      return d; 
   } 
}

次に、Gsonオブジェクトを作成するとき:

Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonDateDeserializer()).create();

これで、私のgsonオブジェクトは.NET日付形式を解析できるようになります(1970年以降のミリス)。

18
mtmurdock

別の解決策は、 ISO 8601 形式を使用することです。これは、Gson側の両方で次のように構成する必要があります。

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();

サーバー側だけでなく、たとえばGlobal.asax.csファイル内のASP.NETMVCの場合、次のようになります。

JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new IsoDateTimeConverter());
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = serializerSettings;

上記のコードの利点は、シリアル化と逆シリアル化の両方を処理するため、日付/時刻の双方向送信が可能になることです。

注:IsoDateTimeConverterクラスは JSON.NETライブラリ の一部です。

11

シリアル化および逆シリアル化の方法a。これをGSONのアダプターとして登録します

JsonSerializer<Date> ser = new JsonSerializer<Date>() {
@Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext 
         context) {
return src == null ? null : new JsonPrimitive(src.getTime());
}
};

JsonDeserializer<Date> deser = new JsonDeserializer<Date>() {
 @Override
 public Date deserialize(JsonElement json, Type typeOfT,
   JsonDeserializationContext context) throws JsonParseException {
return json == null ? null : new Date(json.getAsLong());
 }
 };

Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, ser)
.registerTypeAdapter(Date.class, deser).create();
4
Abiram

このソリューションは、SqlDateTypeAdapterを使用することで機能します。

SqlDateTypeAdapter sqlAdapter = new SqlDateTypeAdapter();
Gson gson = new GsonBuilder()
   .registerTypeAdapter(Java.sql.Date.class, sqlAdapter)
   .setDateFormat("yyyy-MM-dd")
   .create();

参照: https://stackoverflow.com/a/30398307/7308789

2
Houssin Boulla