2015-02-16 9 views
6

Używam biblioteki Retrofit dla moich wywołań REST. JSON, który nadchodzi wygląda tak.Retrofit GSON serializować Data z łańcucha json na długi lub java.lang.Long

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

Jak mogę powiedzieć Modernizacja lub Gson do konwersji na długi?

+0

można użyć konwertera Typ niestandardowy (ale nie wiem jak po prostu ograniczyć jeden z nich do konkretnego pola zamiast całego typu) – njzk2

+0

na marginesie, to 'Z' wygląda st zasięg. Założę się o problem z formatowaniem po stronie serwera. – njzk2

+0

"Z" proste oznacza, że ​​nie ma przesunięcia od UTC - więcej informacji z [wikipedia] (http://en.wikipedia.org/wiki/ISO_8601#UTC) –

Odpowiedz

5

Przeczytaj go w postaci ciągu znaków w twojej POJO następnie użyć getter, aby powrócić go jako długa:

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

ciąg SimpleDateFormat można odwoływać here

+0

@ njzk2 dobra edycja dzięki – pula

+0

To nie działa dla mnie z jakiegoś powodu ... http://pastebin.com/rizyZJR5 – Lion789

+0

@ Lion789 nie widząc twoich wydruków lub naprawdę będąc świadomi różnic między 'DateFormat' a' SimpleDateFormat', powiedziałbym, spróbuj użyć SimpleDateFormat. – pula

0

Można ustawić schemat składniowy w GsonBuilder.setDateFormat() i ustawić obiekt Date w POJO a potem po prostu zadzwonić Date.getMillis()

setDateFormat()

18

Możesz to łatwo zrobić, ustawiając niestandardowy GsonConverter za pomocą własnego obiektu Gson w instancji modernizacji. W swoim POJO można Date created_at; zamiast długiego lub ciąg. Od obiektu daty można użyć numeru created_at.getTime(), aby uzyskać długo, gdy jest to konieczne.

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. 

Można również obsługiwać wiele formatów Data ciągów rejestrując zwyczaj JsonDeserializer na gson przykład używany przez modernizacji

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: \n" + Arrays.toString(DATE_FORMATS)); 
    } 
} 
2

Po przeczytaniu docs, próbowałem tego. Działa, ale nie wiem, czy będzie to miało wpływ na inne typy.

Potrzebowałem mieć dużo w moim POJO, coz nie chcę konwertować przy zapisywaniu do db.

użyłem niestandardową Deserializator

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

i używając go

Gson gson = new GsonBuilder() 
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 
    .setDateFormat(patternFromServer) 
    .registerTypeAdapter(Long.class, deserializer) 
    .create(); 
+0

Dzięki, to działa dla mnie – schwertfisch

+0

Czy potrzebujesz określić .setDateFormat (...)? Mój pracował bez tego. – bMcNees

0

należy używać adaptera typu w danej instancji Gson przez

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

Ale mogę zasugerować, że zamiast używania SimpleDateFormatter przyjrzyj się tej implementacji m Implementacje FasterXML/jackson-databind do obsługi daty ISO8601 w this class i this one. To bardzo zależy od tego, czy analizujesz wiele dat, czy nie.

Należy również zauważyć, że napotkaliśmy problemy z używaniem SimpleDateFormatter wewnątrz aplikacji Android (korzystamy z kombinacji bibliotek Java i Android), gdzie były różne wyniki analizowania w Javie i systemie Android. Korzystanie z powyższych implementacji pomogło rozwiązać ten problem.

To Java implementation i to jest Android implementation, nie definicja Z i X w realizacji Java i brakuje X realizacja w Androidzie

2

Można po prostu użyć tej metody setDateFormat() zrobić to

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

Poniższy kod jest testowany iw końcu działa po wielu staraniach. przed utworzeniem obiektu modernizacyjny utworzyć obiektu Gson

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

i teraz tworzyć modernizacyjny instancję

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

utworzyć te dwie klasy do serializacji i deserializacji format daty

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

    }