2017-08-15 15 views
0

私はSwaggerを使用して、アンドロイドプロジェクトのAPI仕様を定義しています。Swagger:java.text.ParseException:解析できない日付エラー

これが私のGsonBuilderが

public static GsonBuilder gsonBuilder; 

    static { 
    gsonBuilder = new GsonBuilder(); 
    gsonBuilder.serializeNulls(); 
    gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
    } 

私のJSONデータがパラメータ 'のCreationDate' のいずれかを返します。初期化されている方法です。値は2017-08-14To2:42:59.528Zですが、SwaggerモジュールのAPIInvokerメソッドを通過すると、以下のエラーが表示されます。

java.text.parseexception:unparseable date "2017-08-14To2:42:59.528Z" 

'creationDate'パラメータが逆シリアル化されていません。

enter image description here

Iはさらに、コードをデバッグする場合、私はそれがDefaultDateTypeAdapter.javaクラスに失敗していることを見出しました。 deserializeToDateメソッドで3つの形式のいずれかを解析できません。

private Date deserializeToDate(JsonElement json) { 
    synchronized (localFormat) { 
     try { 
     return localFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) { 
     } 
     try { 
     return enUsFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) { 
     } 
     try { 
     return iso8601Format.parse(json.getAsString()); 
     } catch (ParseException e) { 
     throw new JsonSyntaxException(json.getAsString(), e); 
     } 
    } 
    } 

enter image description here

誰もがこのエラーを解決する方法を知っていますか?

注:画像は、エラーについてより明確にするために掲示されています。それは基本的に私が書いたのと同じ情報を示しています。

+0

[質問するときにSOのコードをアップロードしないのはなぜですか?](https://meta.stackoverflow.com/questions/285551/why-not-to-upload-images-of-code-あなたの質問を編集する)、それに応じて質問を編集します。 –

+0

私は自分の質問を更新しました。 –

答えて

0

この質問の回答は解決されました。どうやら、私は自分のgradleアプリケーションファイルにGSONのバージョンは言及していませんでした。したがって、デフォルトでは、2.3.1バージョンと仮定していました。しかし、私のGSONデータは2.7バージョンでした。それが失敗した理由です。

我々はGson 2.3.1バージョンを使用している場合は、defaultdatetypeadapter.javaはあなたがdeserializeToDate方法に気付いた場合、それは3つのフォーマット、

1を生成し、以下の方法

final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> { 

    // TODO: migrate to streaming adapter 

    private final DateFormat enUsFormat; 
    private final DateFormat localFormat; 
    private final DateFormat iso8601Format; 

    DefaultDateTypeAdapter() { 
    this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US), 
     DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); 
    } 

    DefaultDateTypeAdapter(String datePattern) { 
    this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); 
    } 

    DefaultDateTypeAdapter(int style) { 
    this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); 
    } 

    public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { 
    this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), 
     DateFormat.getDateTimeInstance(dateStyle, timeStyle)); 
    } 

    DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) { 
    this.enUsFormat = enUsFormat; 
    this.localFormat = localFormat; 
    this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); 
    this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); 
    } 

    // These methods need to be synchronized since JDK DateFormat classes are not thread-safe 
    // See issue 162 
    public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { 
    synchronized (localFormat) { 
     String dateFormatAsString = enUsFormat.format(src); 
     return new JsonPrimitive(dateFormatAsString); 
    } 
    } 

    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
     throws JsonParseException { 
    if (!(json instanceof JsonPrimitive)) { 
     throw new JsonParseException("The date should be a string value"); 
    } 
    Date date = deserializeToDate(json); 
    if (typeOfT == Date.class) { 
     return date; 
    } else if (typeOfT == Timestamp.class) { 
     return new Timestamp(date.getTime()); 
    } else if (typeOfT == java.sql.Date.class) { 
     return new java.sql.Date(date.getTime()); 
    } else { 
     throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT); 
    } 
    } 

    private Date deserializeToDate(JsonElement json) { 
    synchronized (localFormat) { 
     try { 
     return localFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) { 
     } 
     try { 
     return enUsFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) { 
     } 
     try { 
     return iso8601Format.parse(json.getAsString()); 
     } catch (ParseException e) { 
     throw new JsonSyntaxException(json.getAsString(), e); 
     } 
    } 
    } 

    @Override 
    public String toString() { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(DefaultDateTypeAdapter.class.getSimpleName()); 
    sb.append('(').append(localFormat.getClass().getSimpleName()).append(')'); 
    return sb.toString(); 
    } 
} 

を持っている)ローカルフォーマット

2)enUsFormat

3)iso8601format

ここ

enUsFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")

localFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US) 

localFormatiso8601Format両方とも同じです。パラメータcreationDateの値は2017-08-14To2:42:59.528Zです。なんらかの理由で、3つのフォーマットのいずれかで解析されませんでした。

その後、間違ったGSONバージョンを使用していたことに気付きました。この行をbuild.gradleファイルに含めて、アプリケーションを再度実行しました。

compile 'com.google.code.gson:gson:2.7' 

私はデバッグコードで実行し、各ステップを実行しました。今回は、defaultdatetypeadapter.javaファイルが変更されたことに気付きました。

final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> { 

    // TODO: migrate to streaming adapter 

    private final DateFormat enUsFormat; 
    private final DateFormat localFormat; 

    DefaultDateTypeAdapter() { 
    this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US), 
     DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); 
    } 

    DefaultDateTypeAdapter(String datePattern) { 
    this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); 
    } 

    DefaultDateTypeAdapter(int style) { 
    this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); 
    } 

    public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { 
    this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), 
     DateFormat.getDateTimeInstance(dateStyle, timeStyle)); 
    } 

    DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) { 
    this.enUsFormat = enUsFormat; 
    this.localFormat = localFormat; 
    } 

    // These methods need to be synchronized since JDK DateFormat classes are not thread-safe 
    // See issue 162 
    @Override 
    public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { 
    synchronized (localFormat) { 
     String dateFormatAsString = enUsFormat.format(src); 
     return new JsonPrimitive(dateFormatAsString); 
    } 
    } 

    @Override 
    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
     throws JsonParseException { 
    if (!(json instanceof JsonPrimitive)) { 
     throw new JsonParseException("The date should be a string value"); 
    } 
    Date date = deserializeToDate(json); 
    if (typeOfT == Date.class) { 
     return date; 
    } else if (typeOfT == Timestamp.class) { 
     return new Timestamp(date.getTime()); 
    } else if (typeOfT == java.sql.Date.class) { 
     return new java.sql.Date(date.getTime()); 
    } else { 
     throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT); 
    } 
    } 

    private Date deserializeToDate(JsonElement json) { 
    synchronized (localFormat) { 
     try { 
     return localFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) {} 
     try { 
     return enUsFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) {} 
     try { 
     return ISO8601Utils.parse(json.getAsString(), new ParsePosition(0)); 
     } catch (ParseException e) { 
     throw new JsonSyntaxException(json.getAsString(), e); 
     } 
    } 
    } 

    @Override 
    public String toString() { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(DefaultDateTypeAdapter.class.getSimpleName()); 
    sb.append('(').append(localFormat.getClass().getSimpleName()).append(')'); 
    return sb.toString(); 
    } 
} 

あなたが今deserializeToDate方法に気づいた場合、それは一つの異なるフォーマットを生成し、それを見せていたGSONのバージョンは2.7でした。

1))

2 localFormat)

3 enUsFormat

にこの時間をISO8601Utils、creationDate値が正常ISO8601Utils法により解析されました。

私は最後の1週間の解決策を見つけるのに苦労していました。最後に、build.gradleファイルに1行を含めると、最後にすべての違いが生じました。

この問題は、将来同じ問題に直面している人に役立ちます。

関連する問題