SimpleXmlParser를 지난번에 소개했는데, 잘 안되시나보네요.
제가 테스트해보니, SimpleXmlParser로 코로나19 정보 파싱 매우 잘 됩니다.
윗분의 말처럼, json이 일반적입니다.
그러나 공공데이터API에서 코로나19 정보를 xml로만 주기 때문에
별도 파서를 추가하기 보다는, SimpleXmlParser를 사용하는게
말그대로 가장 심플하죠.
아래와 같이 구현이 가능합니다.
import android.util.Log;
import com.appcognito.retrofit.api.models.SidoInfo;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Query;
public class Covid19 {
private String serviceKey = "여기에 키를 넣는데, 사이트에서 준 urlencoded된 키를 decode해서 넣어야 합니다. 실행시 urlencoding 되기 때문입니다. 쉽게 이야기하면, 문자열에 %가 들어가 있으면 안됩니다.";
public void getSidoInfo() {
try {
// base url - url of web site
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://openapi.data.go.kr/")
.client(new OkHttpClient())
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
ApiDataInterface apiService = retrofit.create(ApiDataInterface.class);
Call<SidoInfo> call = apiService.getData(serviceKey, 10, 1, "20201201", "20201210");
call.enqueue(new Callback<SidoInfo>() {
@Override
public void onResponse(Call<SidoInfo> call, Response<SidoInfo> response) {
SidoInfo resp = response.body();
Log.e("Response success", response.message());
}
@Override
public void onFailure(Call<SidoInfo> call, Throwable t) {
Log.e("Response fail", t.getMessage());
}
});
} catch (Exception e) {
Log.e("Exception", e.getMessage());
}
}
public interface ApiDataInterface{
@GET("openapi/service/rest/Covid19/getCovid19SidoInfStateJson")
@Headers({"Accept: application/xml"})
Call<SidoInfo> getData(@Query("serviceKey") String serviceKey,
@Query("numOfRows") int numOfRows,
@Query("pageNo") int pageNo,
@Query("startCreate_dt") String startCreate_dt,
@Query("endCreateDt") String endCreateDt);
}
}
아래가 데이터 클래스 파일입니다.
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import java.util.List;
@Root(name="response", strict = false)
public class SidoInfo {
@Element(name="header")
public Header header;
@Element(name="body")
public SidoBody body;
@Root(name="header", strict = false)
public static class Header {
@Element(name = "resultCode")
public String resultCode;
@Element(name = "resultMsg")
public String resultMsg;
}
@Root(name="body", strict = false)
public static class SidoBody {
@ElementList(entry = "items")
public List<SidoItem> items;
// public SidoList items;
@Element(name="numOfRows")
public String numOfRows;
@Element(name="pageNo")
public String pageNo;
@Element(name="totalCount")
public String totalCount;
}
@Root(name="item", strict = false)
public static class SidoItem {
@Element(name = "createDt", required = false)
public String createDt;
@Element(name = "deathCnt", required = false)
public String deathCnt;
@Element(name = "defCnt", required = false)
public String defCnt;
@Element(name = "gubun", required = false)
public String gubun;
@Element(name = "gubunCn", required = false)
public String gubunCn;
@Element(name = "gubunEn", required = false)
public String gubunEn;
@Element(name = "incDec", required = false)
public String incDec;
@Element(name = "isolClearCnt", required = false)
public String isolClearCnt;
@Element(name = "isolIngCnt", required = false)
public String isolIngCnt;
@Element(name = "localOccCnt", required = false)
public String localOccCnt;
@Element(name = "overFlowCnt", required = false)
public String overFlowCnt;
@Element(name = "qurRate", required = false)
public String qurRate;
@Element(name = "seq", required = false)
public String seq;
@Element(name = "stdDay", required = false)
public String stdDay;
@Element(name = "updateDt", required = false)
public String updateDt;
}
}
편하게 하기 위해서 하나의 파일에 넣었습니다.
실제로는 각 클래스를 따로 분리해서 사용하는게 좋습니다.
저는 일부러 합쳤네요. 합칠때는 클래스에 static 을 넣어야 하고요.
분리할 때는 static을 빼주세요.
그리고 데이터가 null로 올 경우에는 required = false 체크를 하면 됩니다.
호출할 때는 Activity나 Fragment에서 아래와 같이 하세요.
ServiceKey 때문에, 클래스에 문제가 있는 줄 알고 생각보다 오래걸렸네요..
Covid19 covid19 = new Covid19();
covid19.getSidoInfo();