Development Tip

Retrofit GSON은 json 문자열에서 java.util.date로 날짜를 직렬화합니다.

yourdevel 2020. 10. 22. 22:55
반응형

Retrofit GSON은 json 문자열에서 java.util.date로 날짜를 직렬화합니다.


REST 호출에 Retrofit 라이브러리를 사용하고 있습니다. 내가 한 대부분은 버터처럼 부드럽지만 어떤 이유로 JSON 타임 스탬프 문자열을 java.util.Date객체 로 변환하는 데 문제가 있습니다. 들어오는 JSON은 다음과 같습니다.

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

Retrofit 또는 Gson에게 이러한 문자열을 변환하도록 어떻게 알릴 수 java.util.Date objects있습니까?


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

또는 이에 상응하는 Kotlin :

val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create()
RestAdapter restAdapter = Retrofit.Builder()
    .baseUrl(API_BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()
    .create(T::class.java)

사용자 정의 된 Gson 파서를 개조하도록 설정할 수 있습니다. 더 많은 정보 : Retrofit 웹 사이트

이를 개조 2에서 구현하는 방법을 보려면 Ondreju의 응답을 살펴보십시오.


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

내가 한 방법은 다음과 같습니다.

Date를 확장하는 DateTime 클래스를 만든 다음 사용자 지정 deserializer를 작성합니다.

public class DateTime extends java.util.Date {

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

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

이제 Date 및 DateTime 변환기를 모두 등록하는 deserializer 부분에 대해 :

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

Gson은 사용자 지정 형식으로 구문 분석 할 수없는 경우 하나의 datetime 형식 (빌더에 지정된 형식)과 iso8601 만 처리 할 수 ​​있습니다. 따라서 해결책은 사용자 지정 deserializer를 작성하는 것입니다. 귀하의 문제를 해결하기 위해 정의했습니다.

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

}

이 deserializer 사용 :

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]

문자 그대로 만들려는 클래스에 "created_at"라는 이름의 Date 객체가 이미있는 경우 다음과 같이 쉽습니다.

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

그리고 당신은 끝났습니다. 복잡한 재정의가 필요하지 않습니다.


다음과 같이 두 개의 새 클래스를 정의 할 수 있습니다.

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

마지막으로 사용자 지정 deserializer를 설정합니다.

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

참고URL : https://stackoverflow.com/questions/18473011/retrofit-gson-serialize-date-from-json-string-into-java-util-date

반응형