반응형
Retrofit을 사용하면서 위의 에러가 발생했는데, 확인해보니 String 을 특정 타입으로 변경할때 발생한 에러다.
정확히는 Retrofit이 아닌 Gson 에서 변환하던 중 에러가 발생한 것이다. 샘플을 통해 알아보자.
우선 기존 코드는 다음과 같다
@Getter
@ToString
public class ResponseApiTest {
@SerializedName("date")
private LocalDate date;
@SerializedName("time")
private LocalTime time;
@SerializedName("datetime")
private LocalDateTime datetime;
}
다음 에러가 발생했다.
2021-01-17 15:56:15.827 INFO 18290 --- [ main] okhttp3.OkHttpClient : {"date":"2021-01-17","time":"16:12:56","datetime":"2021-01-17T16:12:56.421271"}
2021-01-17 16:13:43.962 INFO 18840 --- [ main] okhttp3.OkHttpClient : <-- END HTTP (176-byte body)
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 10 path $.date
데이터는 제대로 받아오는거 같은데, 처음엔 의아했다. 그러다 GJON으로 변경하는 과정에서 문제가 발생한걸 알았다.
예를들어 다음과 같이 수정하면 에러가 발생하지 않는다.
@Getter
@ToString
public class ResponseApiTest {
@SerializedName("date")
private String date;
@SerializedName("time")
private String time;
@SerializedName("datetime")
private String datetime;
}
2021-01-17 16:15:08.041 INFO 18886 --- [ main] okhttp3.OkHttpClient : {"date":"2021-01-17","time":"16:15:08","datetime":"2021-01-17T16:15:08.03601"}
2021-01-17 16:15:08.041 INFO 18886 --- [ main] okhttp3.OkHttpClient : <-- END HTTP (175-byte body)
response.body() = ResponseApiTest(date=2021-01-17, time=16:15:08, datetime=2021-01-17T16:15:08.03601)
GSON에서 String을 LocalDate 유형으로 변경하면서 에러가 발생했다.
그래서 이전의 LocalDate 유형을 사용하기 위해서는 GSON의 converter를 등록하는 것을 수정해야 한다.
일전에 Retrofit의 설정은 다음과 같았다.
...
@Bean
public KinsConnectorApi kinsConnectorApi() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(host + ":" + port)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(KinsConnectorApi.class);
}
...
위 설정에서 addConverterFactory에 String을 LocalDate 형식으로 파싱하는 것을 추가해야 한다.
설정에 다음을 추가한다.
...
@Bean
public KinsConnectorApi kinsConnectorApi() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(host + ":" + port)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(KinsConnectorApi.class);
}
// String을 LocalDate, LocalTime, LocalDateTime 으로 변형하는걸 등록한다.
private GsonConverterFactory gsonConverterFactory() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return LocalDateTime.parse(json.getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));
}
})
.registerTypeAdapter(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return LocalDate.parse(json.getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
})
.registerTypeAdapter(LocalTime.class, new JsonDeserializer<LocalTime>() {
@Override
public LocalTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return LocalTime.parse(json.getAsString(), DateTimeFormatter.ofPattern("HH:mm:ss"));
}
})
.create();
return GsonConverterFactory.create(gson);
}
...
Response의 Type을 이전처럼 LocalDate로 변경한다
@Getter
@ToString
public class ResponseApiTest {
@SerializedName("date")
private LocalDate date;
@SerializedName("time")
private LocalTime time;
@SerializedName("datetime")
private LocalDateTime datetime;
}
다시 실행해보자.
2021-01-17 16:22:03.742 INFO 19061 --- [ main] okhttp3.OkHttpClient : {"date":"2021-01-17","time":"16:22:03","datetime":"2021-01-17T16:22:03.736916"}
2021-01-17 16:22:03.742 INFO 19061 --- [ main] okhttp3.OkHttpClient : <-- END HTTP (176-byte body)
response.body() = ResponseApiTest(date=2021-01-17, time=16:22:03, datetime=2021-01-17T16:22:03.736916)
끝.
반응형
'공부 > 프로그래밍' 카테고리의 다른 글
[spring] 객체 내 객체에 @Valid 점검하기 (0) | 2021.01.25 |
---|---|
[java] lambda 를 이용한 GroupBy mulitiple field 사용하기 (1) | 2021.01.20 |
[jpa] 쿼리 로그 설정 (0) | 2021.01.15 |
[axios, react, redux] 서버통신 시 로딩바 띄우기 (0) | 2021.01.13 |
[springboot] 자주쓰는 정보 파라미터에 설정해 자동 주입하여 받기(resolver 사용) (0) | 2021.01.11 |
댓글