현재의 글은 Java8 + RxJava2 + Retrofit2 + OkHttp3 으로 되어 있다.
Kotlin + RxJava2 + Retrofit2 + OkHttp3의 내용을 원하면 아래의 글도 참고해볼 수 있다.
[IT/Android] - [Android] Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $ 에러
JSON 형식의 데이터를 다루다보면 위의 에러를 간혹 접할 수 있다.
위의 에러의 원인은 GSON으로 JSON데이터를 파싱할 때 형식이 맞지 않아서 발생하는 에러이다.
문제의 원인을 살펴보자.
일반적인 JSON의 데이터는 아래와 같이 되어있다.
{
"name": "Apple",
"family": "Fruit",
"age": 12,
"weight": 4.2,
"brother": [
{"name": "Banana", "family": "Fruit", "age": 12, "weight": 3.5},
{"name": "Melon", "family": "Fruit", "age": 31, "weight": 6.1},
{"name": "Fish", "family": "Fish", "age": 2, "weight": 1.1}
]
}
그러나 위의 에러가 발생할 때의 JSON의 데이터 형식을 보면 아래와 같이 되어있는 경우가 종종있다.
반드시 아래와 같은 상황은 아니지만 참고할 수 있는 상황이다. 밑의 예제는 JSON데이터가 처음부터 Array로 시작되는 경우이다.
[
{
"name": "Apple",
"family": "Fruit",
"age": 12,
"weight": 4.2
},
{
"brother": [
{"name": "Banana", "family": "Fruit", "age": 12, "weight": 3.5},
{"name": "Melon", "family": "Fruit", "age": 31, "weight": 6.1},
{"name": "Fish", "family": "Fish", "age": 2, "weight": 1.1}
]
}
]
Retrofit2 와 RxJava2를 이용해서 네트워킹 프로그래밍을 주로 사용하게 되고, 결과값은 JSON데이터를 다루게 되는 경우가 많을 것이다.
HTTP인터페이스를 만들고 POJO 클래스를 만들어서 Retrofit에 GSON컨버터를 붙이고 RxJava로 비동기 프로그래밍을 이용하여 결과값을 컨트롤하게 될 것이다.
수정을 해야할 부분은, HTTP인터페이스 부분과 RxJava로 결과값 호출하는 부분을 수정해야 할 확률이 높다.
// Retrofit2 interface 에러 해결 전
@GET("Address.jsp")
Single<JsonData> GetJsonData(
@Query(value="apiKey", encoded=true) String apiKey,
@Query("page") String page,
@Query("count") String count
);
// Retrofit2 interface 에러 해결 후
// JsonData를 Array 형태로 변경한 것을 볼 수 있다.
@GET("Address.jsp")
Single<JsonData[]> GetJsonData(
@Query(value="apiKey", encoded=true) String apiKey,
@Query("page") String page,
@Query("count") String count
);
// MainActivity 에서 Retrofit2 + RxJava2로 호출하는 부분 수정 전
RestfulAdapter.getInstance(this)
.GetJsonData(
getString(R.string.http_apikey),
"30",
"1")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
})
.unsubscribeOn(Schedulers.io())
.subscribe(new Consumer<JsonData>() {
@Override
public void accept(JsonData JsonData) throws Exception {
Toast.makeText(MainActivity.this, JsonData.getList().size(), Toast.LENGTH_SHORT).show();
}
});
// MainActivity 에서 Retrofit2 + RxJava2로 호출하는 부분 수정 후
RestfulAdapter.getInstance(this)
.GetJsonData(
getString(R.string.http_apikey),
"30",
"1")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError(new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
})
.unsubscribeOn(Schedulers.io())
.subscribe(new Consumer<JsonData[]>() {
@Override
public void accept(JsonData[] JsonData) throws Exception {
Toast.makeText(MainActivity.this, JsonData[1].getList().size(), Toast.LENGTH_SHORT).show();
}
});
위와 같이 JsonData부분은 JsonData[]와 같이 수정해서 사용하면 에러가 해결된다.
Json데이터를 설계할 때 서버에서 받아오는 결과값과 앱에서 처리하는 데이터 형식을 잘 맞춰야한다.
'IT > Android' 카테고리의 다른 글
Android webview 사용 방법 및 팁(모바일 화면 맞추기, 줌 기능 사용) (0) | 2019.06.13 |
---|---|
프래그먼트에서 백키로 이전 프래그먼트로 이동하기(Go to the previous Fragment by backKey) (0) | 2019.06.04 |
ADB 명령어로 스마트폰에서 앱 삭제하기(삼성 갤럭시, LG G/V시리즈) (0) | 2019.04.23 |
[해상도 변경] Pixel 2 XL(픽셀2XL) 해상도 변경하기(QHD+ 를 FHD+ 로) (0) | 2019.03.08 |
[Android] Recyclerview 에서 마지막 아이템 판단하는 방법(Detect when the RecyclerView reaches the bottom) (0) | 2019.02.08 |