2013-08-27 30 views
58

我爲我的REST調用使用了Retrofit庫。我所做的大部分工作都很流暢,但由於某些原因,我有問題會將JSON時間戳字符串轉換爲java.util.Date對象。即將到來的JSON看起來像這樣。改造GSON序列化將json字符串中的日期轉換爲java.util.date

{ 
    "date": "2013-07-16", 
    "created_at": "2013-07-16T22:52:36Z", 
} 

我怎麼能告訴改造或GSON將這些字符串轉換爲java.util.Date objects

+0

貌似[這個問題]的副本(http://stackoverflow.com/questions/6696082/set-date -format功能於GSON功能於JSP)。 – Davmrtl

+0

@Davmrtl:它不一樣,因爲這裏有兩種不同的日期格式。所以它需要一種不同的方法。 – giampaolo

回答

102
Gson gson = new GsonBuilder() 
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss") 
.create(); 

RestAdapter restAdapter = new RestAdapter.Builder() 
.setEndpoint(API_BASE_URL) 
.setConverter(new GsonConverter.create(gson)) 
.build(); 

您可以設置自定義的Gson解析器進行翻新。更多在這裏:Retrofit Website

看Ondreju的反應,看看如何在改造2

+7

請詳細解釋您的代碼,以便它對OP和其他讀者更有用。 –

+2

謝謝你!你節省了我的一天一夜! – digaomatias

+0

我如何爲我的所有要求做到這一點?所以把它添加到我的'ServiceGenerator'? – Zapnologica

7

如果不能使用自定義格式進行分析,Gson只能處理一種日期時間格式(在構建器中指定的格式)加上iso8601。因此,解決方案可能是編寫您的自定義解串器。與此解串器

package stackoverflow.questions.q18473011; 

import java.util.Date; 

public class Foo { 

    Date date; 
    Date created_at; 

    public Foo(Date date, Date created_at){ 
     this.date = date; 
     this.created_at = created_at; 
    } 

    @Override 
    public String toString() { 
     return "Foo [date=" + date + ", created_at=" + created_at + "]"; 
    } 

} 

:爲了解決你的問題,我定義

package stackoverflow.questions.q18473011; 

import java.lang.reflect.Type; 
import java.text.*; 
import java.util.Date; 

import com.google.gson.*; 

public class FooDeserializer implements JsonDeserializer<Foo> { 

    public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 

     String a = json.getAsJsonObject().get("date").getAsString(); 
     String b = json.getAsJsonObject().get("created_at").getAsString(); 

     SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd"); 
     SimpleDateFormat sdfDateWithTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

     Date date, created; 
     try { 
      date = sdfDate.parse(a); 
      created = sdfDateWithTime.parse(b); 
     } catch (ParseException e) { 
      throw new RuntimeException(e); 
     } 

     return new Foo(date, created); 
    } 

} 

最後一步是創建一個Gson實例與正確的適配器:

package stackoverflow.questions.q18473011; 

import com.google.gson.*; 

public class Question { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     String s = "{ \"date\": \"2013-07-16\", \"created_at\": \"2013-07-16T22:52:36Z\"}"; 


     GsonBuilder builder = new GsonBuilder(); 
     builder.registerTypeAdapter(Foo.class, new FooDeserializer()); 

     Gson gson = builder.create(); 
     Foo myObject = gson.fromJson(s, Foo.class); 

     System.out.println("Result: "+myObject); 
    } 

} 

我的結果:

Result: Foo [date=Tue Jul 16 00:00:00 CEST 2013, created_at=Tue Jul 16 22:52:36 CEST 2013] 
11

這裏實現我這是怎麼做的:

創建DateTime類擴展日期,然後寫一個自定義解串器:

public class DateTime extends java.util.Date { 

    public DateTime(long readLong) { 
     super(readLong); 
    } 

    public DateTime(Date date) { 
     super(date.getTime()); 
    }  
} 

現在對於我們註冊日期和日期時間轉換器和解串器部分:

public static Gson gsonWithDate(){ 
    final GsonBuilder builder = new GsonBuilder(); 

    builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { 

     final DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 
     @Override 
     public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
      try { 
       return df.parse(json.getAsString()); 
      } catch (final java.text.ParseException e) { 
       e.printStackTrace(); 
       return null; 
      } 
     } 
    }); 

    builder.registerTypeAdapter(DateTime.class, new JsonDeserializer<DateTime>() { 

     final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
     @Override 
     public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
      try { 
       return new DateTime(df.parse(json.getAsString())); 
      } catch (final java.text.ParseException e) { 
       e.printStackTrace(); 
       return null; 
      } 
     } 
    }); 

    return builder.create(); 
} 

當您創建RestAdapter,請執行以下操作:

new RestAdapter.Builder().setConverter(gsonWithDate()); 

你的Foo應該是這樣的:

class Foo { 
    Date date; 
    DateTime created_at; 
} 
+0

謝謝!我只需要從'return df.parse(json.getAsString());'改爲'long timeStamp = Long.parseLong(json.getAsString());返回新的java.util.Date(timeStamp);' – Juancho

+0

太棒了!謝謝! – NickUnuchek

1

毫不誇張地說,如果你已經有了一個名爲「created_at」的Date對象在你正在創建的課程中,這很容易:

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create(); 
YourObject parsedObject1 = gson.fromJson(JsonStringYouGotSomehow, YourObject.class); 

然後你就完成了。沒有複雜的覆蓋需要。

1

你可以這樣定義兩個新類:

import java.util.Date; 

public class MyDate extends Date { 
} 

import java.util.Date; 

public class CreatedAtDate extends Date { 
} 

你的POJO會是這樣:

import MyDate; 
import CreatedAtDate; 

public class Foo { 
    MyDate date; 
    CreatedAtDate created_at; 
} 

最後設置自定義解串器:

public class MyDateDeserializer implements JsonDeserializer<Date> { 

    public static final SimpleDateFormat sServerDateDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 

    @Override 
    public MyDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     if (json != null) { 
      final String jsonString = json.getAsString(); 
      try { 
       return (MyDate) sServerDateDateFormat.parse(jsonString); 
      } catch (ParseException e) { 
       e.printStackTrace(); 
      } 
     } 
     return null; 
    } 
} 
@ gderaco的回答更新改造2.

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapter(MyDate.class, new MyDateDeserializer()); 
55

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

Retrofit retrofitAdapter = new Retrofit.Builder() 
.baseUrl(API_BASE_URL) 
.addConverterFactory(GsonConverterFactory.create(gson)) 
.build(); 
+2

複製日期格式時請注意引號 - 我有問題! – LukTar