diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 7b23deac..7166aac7 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -30,6 +30,7 @@ import com.google.gson.internal.bind.MapTypeAdapterFactory; import com.google.gson.internal.bind.MiniGson; import com.google.gson.internal.bind.ObjectTypeAdapter; import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; +import com.google.gson.internal.bind.SqlDateTypeAdapter; import com.google.gson.internal.bind.TimeTypeAdapter; import com.google.gson.internal.bind.TypeAdapter; import com.google.gson.internal.bind.TypeAdapters; @@ -259,8 +260,8 @@ public final class Gson { .factory(DateTypeAdapter.FACTORY) .factory(TypeAdapters.CALENDAR_FACTORY) .factory(TimeTypeAdapter.FACTORY) - .factory(TypeAdapters.SQL_DATE_FACTORY) - .factory(TypeAdapters.SQL_TIMESTAMP_FACTORY) + .factory(SqlDateTypeAdapter.FACTORY) + .factory(TypeAdapters.TIMESTAMP_FACTORY) .factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)) .factory(ArrayTypeAdapter.FACTORY) .factory(TypeAdapters.ENUM_FACTORY) diff --git a/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java index cd97c5af..ea6f36bb 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java @@ -29,7 +29,7 @@ import java.util.Locale; import java.util.TimeZone; /** - * Adapter for Time. Although this class appears stateless, it is not. + * Adapter for Date. Although this class appears stateless, it is not. * DateFormat captures its time zone and locale when it is created, which gives * this class state. DateFormat isn't thread safe either, so this class has * to synchronize its read and write methods. diff --git a/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java new file mode 100644 index 00000000..460994cd --- /dev/null +++ b/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gson.internal.bind; + +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/** + * Adapter for java.sql.Date. Although this class appears stateless, it is not. + * DateFormat captures its time zone and locale when it is created, which gives + * this class state. DateFormat isn't thread safe either, so this class has + * to synchronize its read and write methods. + */ +public final class SqlDateTypeAdapter extends TypeAdapter { + public static final Factory FACTORY = new Factory() { + @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal + public TypeAdapter create(MiniGson context, TypeToken typeToken) { + return typeToken.getRawType() == java.sql.Date.class + ? (TypeAdapter) new SqlDateTypeAdapter() : null; + } + }; + + private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); + + @Override + public synchronized java.sql.Date read(JsonReader reader) throws IOException { + try { + final long utilDate = format.parse(reader.nextString()).getTime(); + return new java.sql.Date(utilDate); + } catch (ParseException e) { + throw new JsonSyntaxException(e); + } + } + + @Override + public synchronized void write(JsonWriter writer, java.sql.Date value) throws IOException { + writer.value(format.format(value)); + } +} diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java index f9fcedf0..07d764a9 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java @@ -29,9 +29,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.sql.Timestamp; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.BitSet; import java.util.Calendar; import java.util.Date; @@ -53,7 +50,7 @@ public final class TypeAdapters { int i = 0; JsonToken tokenType = reader.peek(); while (tokenType != JsonToken.END_ARRAY) { - boolean set = false; + boolean set; switch (tokenType) { case NUMBER: set = reader.nextInt() != 0; @@ -411,52 +408,27 @@ public final class TypeAdapters { public static final TypeAdapter.Factory UUID_FACTORY = newFactory(UUID.class, UUID); - private static final class TimestampTypeAdapter extends TypeAdapter { - private final MiniGson context; - public TimestampTypeAdapter(MiniGson context) { - this.context = context; - } - @Override - public Timestamp read(JsonReader reader) throws IOException { - TypeAdapter dateTypeAdapter = context.getAdapter(Date.class); - Date date = dateTypeAdapter.read(reader); - return new java.sql.Timestamp(date.getTime()); - } - @Override - public void write(JsonWriter writer, Timestamp value) throws IOException { - TypeAdapter dateTypeAdapter = context.getAdapter(Date.class); - dateTypeAdapter.write(writer, value); - } - }; - public static final TypeAdapter.Factory SQL_TIMESTAMP_FACTORY = new TypeAdapter.Factory() { - @SuppressWarnings("unchecked") + public static final TypeAdapter.Factory TIMESTAMP_FACTORY = new TypeAdapter.Factory() { + @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal public TypeAdapter create(MiniGson context, TypeToken typeToken) { - return typeToken.getRawType() == Timestamp.class - ? (TypeAdapter) new TimestampTypeAdapter(context) : null; - } - }; - - public static final TypeAdapter SQL_DATE = new TypeAdapter() { - private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); - @Override - public java.sql.Date read(JsonReader reader) throws IOException { - try { - synchronized (format) { - Date date = format.parse(reader.nextString()); - return new java.sql.Date(date.getTime()); - } - } catch (ParseException e) { - throw new JsonSyntaxException(e); + if (typeToken.getRawType() != Timestamp.class) { + return null; } - } - @Override - public void write(JsonWriter writer, java.sql.Date value) throws IOException { - writer.value(format.format(value)); + + final TypeAdapter dateTypeAdapter = context.getAdapter(Date.class); + return (TypeAdapter) new TypeAdapter() { + @Override public Timestamp read(JsonReader reader) throws IOException { + Date date = dateTypeAdapter.read(reader); + return new Timestamp(date.getTime()); + } + + @Override public void write(JsonWriter writer, Timestamp value) throws IOException { + dateTypeAdapter.write(writer, value); + } + }; } }; - public static final TypeAdapter.Factory SQL_DATE_FACTORY = newFactory(java.sql.Date.class, SQL_DATE); - public static final TypeAdapter CALENDAR = new TypeAdapter() { private static final String YEAR = "year"; private static final String MONTH = "month"; @@ -633,4 +605,5 @@ public final class TypeAdapters { } }; } + }