2013-08-27 4 views
58

Я использую библиотеку «Модернизация» для моих вызовов REST. Большинство из того, что я сделал, было гладким, как масло, но по какой-то причине у меня возникают проблемы с преобразованием строк времени JSON в объекты java.util.Date. JSON, который идет, выглядит так.Retrofit GSON serialize Дата из json string в 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()); 
    }  
} 

Теперь для десериализации части, где мы регистрируем как даты и DateTime преобразователи:

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());' to 'long timeStamp = Long.parseLong (json.getAsString()); return new java.util.Date (timeStamp); ' – Juancho

+0

Отлично! Спасибо! – NickUnuchek

1

В буквальном смысле слова, если у вас уже есть объект Date с именем «created_at» в классе, который вы создаете, это легко:

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

и

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

@ ответ gderaco обновляется для модификации 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

Следите за кавычками при копировании формата даты - у меня была проблема с этим! – LukTar

Смежные вопросы