“无法解析的日期:1302828677828”试图用 Gson 反序列化从服务器接收到的毫秒格式日期
Posted
技术标签:
【中文标题】“无法解析的日期:1302828677828”试图用 Gson 反序列化从服务器接收到的毫秒格式日期【英文标题】:"Unparseable date: 1302828677828" trying to deserialize with Gson a millisecond-format date received from server 【发布时间】:2011-08-05 23:53:30 【问题描述】:在 4 小时不停地尝试解决问题后,我决定在这里询问是否有人可以帮助我。
问题是我的 android 客户端在尝试反序列化从服务器接收的数据时抛出“Unparseable: 1302828677828”异常。
我想知道是否可以使用 Gson 反序列化毫秒格式的日期。
【问题讨论】:
这应该代表什么日期/时间? 您不能将其解析为long
,然后在您的代码中以编程方式将long
转换为Date
?
最后我得到了解决方案: // 创建一个 json 对象来管理接收到的信息 GsonBuilder builder = new GsonBuilder(); // 注册一个适配器来将日期类型管理为长值 builder.registerTypeAdapter(Date.class, new JsonDeserializer由于某种原因,我在 Intellij 中使用匿名类的上述代码出现了编译错误;一个 lambda 对我有用:
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();
【讨论】:
【参考方案2】:在处理 JSON 时使用下面的 sn-p 将毫秒转换为日期。
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();
【讨论】:
【参考方案3】: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();
【讨论】:
【参考方案4】:我编写了一个基于 GSON 默认 DateTypeAdapter 的改进型DateTypeAdapter,它支持默认日期格式和时间戳(长)格式。
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();
【讨论】:
【参考方案5】:当我尝试使用 Rest client 的 Android annotations 库反序列化 DateTime 字段时,我遇到了同样的问题。 作为解决方案,我创建了自定义 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 客户端中定义它
@Rest(rootUrl = "http://192.168.1.1:8080", converters = CustomGsonHttpMessageConverter.class)
public interface RestClient extends RestClientErrorHandling
...
希望对你有帮助
【讨论】:
【参考方案6】:阿方索的评论:
终于找到了解决办法:
// 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()); ); Gson gson = builder.create();
【讨论】:
非常感谢您节省了我的时间!! 时区问题 感谢这对我也有帮助。虽然我将它用于时间戳。 这适用于以毫秒为单位传递的每个日期,而不是为每种已解析对象传递规则.getAsJsonPrimitive()
可以省略,而使用 Java 8 lambda 则更短:Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
以上是关于“无法解析的日期:1302828677828”试图用 Gson 反序列化从服务器接收到的毫秒格式日期的主要内容,如果未能解决你的问题,请参考以下文章