После 4 часов непрерывных попыток решить проблему я решил спросить здесь, может ли кто-нибудь мне помочь.
Проблема в том, что мой клиент Android при попытке десериализации данных, полученных от сервера, выдает исключение «Unparseable: 1302828677828».
Я хотел бы знать, можно ли десериализовать дату в миллисекундном формате с помощью Gson.
long
, а затем программно преобразоватьlong
егоDate
в свой код?Ответы:
Комментарий Альфонсо:
источник
.getAsJsonPrimitive()
можно опустить, а сGson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
Я написал ImprovedDateTypeAdapter на основе DateTypeAdapter по умолчанию GSON, который поддерживает формат даты по умолчанию и формат временной метки (длинный).
import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; public final class ImprovedDateTypeAdapter extends TypeAdapter<Date> { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { @SuppressWarnings("unchecked") TypeAdapter<T> typeAdapter = (TypeAdapter<T>) ((typeToken.getRawType() == Date.class) ? new ImprovedDateTypeAdapter() : null); return typeAdapter; } }; private final DateFormat enUsFormat; private final DateFormat localFormat; private final DateFormat iso8601Format; public ImprovedDateTypeAdapter() { this.enUsFormat = DateFormat.getDateTimeInstance(2, 2, Locale.US); this.localFormat = DateFormat.getDateTimeInstance(2, 2); this.iso8601Format = buildIso8601Format(); } private static DateFormat buildIso8601Format() { DateFormat iso8601Format = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); return iso8601Format; } public Date read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } return deserializeToDate(in.nextString()); } private synchronized Date deserializeToDate(String json) { try { return new Date(Long.parseLong(json)); } catch (Exception e) { try { return this.localFormat.parse(json); } catch (ParseException e1) { try { return this.enUsFormat.parse(json); } catch (ParseException e2) { try { return this.iso8601Format.parse(json); } catch (ParseException e3) { throw new JsonSyntaxException(json, e3); } } } } } public synchronized void write(JsonWriter out, Date value) throws IOException { if (value == null) { out.nullValue(); return; } String dateFormatAsString = this.enUsFormat.format(value); out.value(dateFormatAsString); } }
Чтобы использовать это:
// Creates the json object which will manage the information received GsonBuilder builder = new GsonBuilder(); // Register an adapter to manage the date types as long values builder.registerTypeAdapter(Date.class, new ImprovedDateTypeAdapter()); Gson gson = builder.create();
источник
JsonSerializer<Date> serializer= new JsonSerializer<Date>() { @Override public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { return src == null ? null : new JsonPrimitive(src.getTime()); } }; JsonDeserializer<Date> deserializer= 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, serializer) .registerTypeAdapter(Date.class, deserializer).create();
источник
Используйте приведенный ниже фрагмент для преобразования миллисекунд в дату при обработке JSON.
GsonBuilder gsonBuilder = new GsonBuilder(); // Adapter to convert long values to date types gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { public Date deserialize(JsonElement jsonElement, Type typeOfObj, JsonDeserializationContext context) throws JsonParseException { //Converting milliseconds to current Date. (instead of 1970) return new Date(jsonElement.getAsLong() * 1000); } }); Gson gson = gsonBuilder.setPrettyPrinting().create();
источник
У меня такая же проблема , когда я попытался десериализация DateTime поля с Rest клиентом из Android аннотаций библиотеки. В качестве решения я создал собственный GsonHttpMessageConverter
public class CustomGsonHttpMessageConverter extends GsonHttpMessageConverter { public CustomGsonHttpMessageConverter() { // Creates the json object which will manage the information received GsonBuilder builder = new GsonBuilder(); // Register an adapter to manage the date types as long values builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new Date(json.getAsJsonPrimitive().getAsLong()); } }); setGson(builder.create()); } }
и определите его в клиенте отдыха
@Rest(rootUrl = "http://192.168.1.1:8080", converters = {CustomGsonHttpMessageConverter.class}) public interface RestClient extends RestClientErrorHandling { ...
Я надеюсь это будет полезно
источник
По какой-то причине у меня были ошибки компиляции в Intellij с приведенным выше кодом с использованием анонимного класса; лямбда работала для меня:
private static Gson buildGson(){ // Deserialize longs as Dates final JsonDeserializer<Date> dateDeserializer = (json, type, context) -> json == null ? null : new Date(json.getAsLong()); return new GsonBuilder().registerTypeAdapter(Date.class, dateDeserializer).create(); }
источник