关于android:Retrofit GSON将json字符串中的Date序列化为long或java.lang.Long

Retrofit GSON serialize Date from json string into long or java.lang.Long

我正在使用Retrofit库进行REST调用。
传入的JSON看起来像这样。

1
2
3
{
   "created_at":"2013-07-16T22:52:36Z",
}

如何告诉Retrofit或Gson将其转换为long?


您可以通过在改造实例上使用您自己的Gson对象设置自定义GsonConverter来轻松地做到这一点。在POJO中,您可以Date created_at;代替long或String。在日期对象中,可以根据需要使用created_at.getTime()来获取long。

1
2
3
4
5
6
7
8
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssz")
.create();

RestAdapter.Builder builder = new RestAdapter.Builder();
// Use a custom GSON converter
builder.setConverter(new GsonConverter(gson));
..... create retrofit service.

您还可以通过在Retrofit

使用的gson实例上注册自定义JsonDeserializer来支持多种日期字符串格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new DateTypeDeserializer());

public class DateTypeDeserializer implements JsonDeserializer<Date> {
    private static final String[] DATE_FORMATS = new String[]{
           "yyyy-MM-dd'T'HH:mm:ssZ",
           "yyyy-MM-dd'T'HH:mm:ss",
           "yyyy-MM-dd",
           "EEE MMM dd HH:mm:ss z yyyy",
           "HH:mm:ss",
           "MM/dd/yyyy HH:mm:ss aaa",
           "yyyy-MM-dd'T'HH:mm:ss.SSSSSS",
           "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS",
           "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'",
           "MMM d',' yyyy H:mm:ss a"
    };

    @Override
    public Date deserialize(JsonElement jsonElement, Type typeOF, JsonDeserializationContext context) throws JsonParseException {
        for (String format : DATE_FORMATS) {
            try {
                return new SimpleDateFormat(format, Locale.US).parse(jsonElement.getAsString());
            } catch (ParseException e) {
            }
        }
        throw new JsonParseException("Unparseable date: "" + jsonElement.getAsString()
                +"
". Supported formats: \
"
+ Arrays.toString(DATE_FORMATS));
    }
}

在您的POJO中以字符串形式读取它,然后使用getter将其返回为long:

1
2
3
4
5
6
7
8
9
String created_at;

public long getCreatedAt(){
    SimpleDateFormat formatter = new
              SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    Date createDate = formatter.parse(created_at);

    return createDate.getTime();
 }

在这里可以引用SimpleDateFormat字符串


您可以简单地使用此setDateFormat()方法进行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class RestClient
{
    private static final String BASE_URL ="your base url";
    private ApiService apiService;

    public RestClient()
    {
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
                .create();

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(BASE_URL)
                .setConverter(new GsonConverter(gson))
                .build();

        apiService = restAdapter.create(ApiService.class);
    }

    public ApiService getApiService()
    {
        return apiService;
    }
}


阅读文档后,我尝试了此操作。它有效,但我不知道它是否会对其他类型有任何影响。

我的POJO需要很长的时间,因为保存到db时我不想转换。

我使用了自定义解串器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
JsonDeserializer<Long> deserializer = new JsonDeserializer<Long>() {
    @Override
    public Long deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context) throws JsonParseException {
        try{
            if(json==null){
               return new Long(0);
            }
            else{
                String dateString = json.getAsString();
                long dateLong = DateFormatUtil.getLongServerTime(dateString);
                return new Long(dateLong);
            }
        }
        catch(ParseException e){
            return new Long(0);
        }
    }
};

并使用它

1
2
3
4
5
Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .setDateFormat(patternFromServer)
    .registerTypeAdapter(Long.class, deserializer)
    .create();


下面的代码已经过测试,并且经过大量的努力终于可以正常工作。
在创建改造对象之前,请创建Gson对象

1
2
3
4
 Gson gson = new GsonBuilder()
                .registerTypeAdapter(Date.class, new DateDeserializer())
                .registerTypeAdapter(Date.class, new DateSerializer())
                .create();

,现在创建改造实例

1
2
3
4
 Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("URL")
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();

创建这两个类以序列化和反序列化日期格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static class DateDeserializer implements JsonDeserializer<Date> {

        private final String TAG = DateDeserializer.class.getSimpleName();

        @Override
        public Date deserialize(JsonElement element, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
            String date = element.getAsString();

            SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
            formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
            Date returnDate = null;
            try {
                returnDate = formatter.parse(date);
            } catch (ParseException e) {
                Log.e(TAG,"Date parser exception:", e);
                returnDate = null;
            }
            return returnDate;
        }
    }

    static class DateSerializer implements JsonSerializer<Date> {

        private final String TAG = DateSerializer.class.getSimpleName();

        @Override
        public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
            SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
            formatter.setTimeZone(TimeZone.getDefault());
            String dateFormatAsString = formatter.format(date);
            return new JsonPrimitive(dateFormatAsString);
        }

    }


您应该通过

Gson实例中使用类型适配器

1
2
3
new GsonBuilder()
    .registerTypeAdapter(Date.class, [date deserializer class here])
    .create

但是我可以建议您代替使用SimpleDateFormatter,而是从FasterXML / jackson-databind实现中查看该实现,以用于此类和该类中的ISO8601日期处理。这在很大程度上取决于您是否要解析很多日期。

还请注意,我们在Android应用程序(我们使用Java和Android库的组合)中使用SimpleDateFormatter时遇到了问题,在Java和Android中进行解析的结果不同。使用上述实现有助于解决此问题。

这是Java实现,这是Android实现,不是Java实现中ZX的定义以及Android

中缺少的X实现


您可以在GsonBuilder.setDateFormat()中设置解析模式,并在POJO中设置Date对象,然后只需调用Date.getMillis()

setDateFormat()