2013-08-27 35 views
58

Tôi đang sử dụng thư viện Retrofit cho các cuộc gọi REST của mình. Hầu hết những gì tôi đã làm đã được mịn màng như bơ nhưng đối với một số lý do tôi đang gặp vấn đề chuyển đổi chuỗi thời gian JSON thành các đối tượng java.util.Date. JSON xuất hiện trông như thế này.Trang bị thêm GSON serialize Ngày từ chuỗi json vào java.util.date

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

Làm cách nào tôi có thể yêu cầu Retrofit hoặc Gson chuyển đổi các chuỗi này thành java.util.Date objects?

+0

Trông giống như một bản sao của [câu hỏi này] (http://stackoverflow.com/questions/6696082/set-date -format-in-gson-in-jsp). – Davmrtl

+0

@Davmrtl: không giống nhau vì có hai định dạng ngày khác nhau tại đây. Vì vậy, nó đòi hỏi một cách tiếp cận khác nhau. – giampaolo

Trả lời

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(); 

Bạn có thể đặt trình phân tích cú pháp Gson tùy chỉnh của bạn để trang bị thêm. thêm ở đây: Retrofit Website

Nhìn vào phản ứng Ondreju để xem làm thế nào để thực hiện điều này trong trang bị thêm 2

+7

Vui lòng giải thích ngắn gọn mã của bạn để nó hữu ích hơn cho OP và các độc giả khác. –

+2

Cảm ơn người đàn ông! Bạn đã lưu ngày/đêm của tôi! – digaomatias

+0

Tôi làm cách nào để thực hiện điều này cho tất cả các yêu cầu của mình? Vì vậy, thêm nó vào 'ServiceGenerator' của tôi? – Zapnologica

7

Gson chỉ có thể xử lý một định dạng ngày giờ (được chỉ định trong trình tạo) cộng với iso8601 nếu phân tích cú pháp với định dạng tùy chỉnh là không thể. Vì vậy, một giải pháp có thể được để viết deserializer tùy chỉnh của bạn. Để giải quyết vấn đề của bạn tôi đã xác định:

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 + "]"; 
    } 

} 

với deserializer này:

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); 
    } 

} 

Bước cuối cùng là tạo ra một trường hợp Gson với bộ chuyển đổi đúng:

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); 
    } 

} 

kết quả của tôi:

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

Sau đây là cách tôi đã làm nó:

Tạo lớp DateTime kéo dài ngày và sau đó viết một deserializer tùy chỉnh:

public class DateTime extends java.util.Date { 

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

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

Đây là phần deserializer nơi chúng tôi đăng ký cả ngày và DateTime chuyển đổi:

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(); 
} 

Và khi bạn tạo RestAdapter của bạn, làm như sau:

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

Foo của bạn sẽ trông như thế này:

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

Cảm ơn! Tôi chỉ phải thay đổi từ 'return df.parse (json.getAsString());' thành 'long timeStamp = Long.parseLong (json.getAsString()); trả lại java.util.Date mới (timeStamp); ' – Juancho

+0

Tuyệt vời! Cảm ơn bạn! – NickUnuchek

1

Khá nghĩa là nếu bạn đã có một đối tượng ngày với tên "created_at" trong lớp học bạn đang tạo sau đó nó là dễ dàng:

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

Và bạn đã hoàn tất. không cần ghi đè phức tạp.

1

Bạn có thể định nghĩa hai lớp nhân vật mới như thế này:

import java.util.Date; 

public class MyDate extends Date { 
} 

import java.util.Date; 

public class CreatedAtDate extends Date { 
} 

POJO của bạn sẽ như thế này:

import MyDate; 
import CreatedAtDate; 

public class Foo { 
    MyDate date; 
    CreatedAtDate created_at; 
} 

Cuối cùng đặt deserializer tùy chỉnh của bạn:

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; 
    } 
} 

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

@ câu trả lời gderaco của cập nhật để trang bị thêm 2.0:

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

Xem dấu ngoặc kép khi sao chép định dạng ngày - Tôi gặp vấn đề với điều đó! – LukTar