본문 바로가기
Android/Concepts

Gson을 이용하여 Json 파싱하기

by JuHy_ 2020. 4. 27.

Json이란?

서버에 요청을 보내고 응답을 받는 과정에서 String 데이터를 주고받게 된다.

이 때 단순한 String 데이터가 아닌 여러 종류의 데이터를 String 형태로 전달하기 위한 형식이 Json이다.

정해진 규칙대로 데이터를 문자열로 바꾸고, 문자열을 다시 데이터로 바꿈으로써 복잡한 데이터를 전송할 수 있다.

 

Json 문자열은 다음과 같은 규칙을 따른다.

 

1. key와 value의 값은 각각 큰따옴표( " " )로 감싸며 콜론( : )으로 구분한다.

(value 값은 기본적인 자료형 뿐만 아니라 Json 객체 혹은 배열도 가능)

 

2. 객체는 중괄호( { } )로 감싸며, 데이터들은 콤마( , )로 구분한다.

 

3. 배열은 대괄호( [ ] )로 감싸며, 데이터들은 콤마( , )로 구분한다.

 

Gson이란?

Json을 이용하여 데이터를 전달하려면 Json 형식에 맞춰 데이터를 조합하고, 해석하는 과정이 필요하다.

이 과정을 직접 구현하려면 문자열을 기호에 따라 분리하고 합치는 복잡한 코드를 작성해야 한다.

이를 간단하게 사용할 수 있도록 구글에서는 Gson 라이브러리를 제공하고 있다.

 

Gson 라이브러리는 Json 문자열을 해석하여 객체로 만들고, 객체를 Json 문자열로 만드는 기능을 제공한다.

이를 이용하여 개발자는 직접 복잡한 코드를 구현하지 않고 Json 형식을 사용할 수 있다.

 

Gson 사용법

영화관입장권통합전산망 open api로부터 sample json 데이터를 받아와 분석해보자.

https://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=430156241533f1d058c603178cc3ca0e&targetDt=20120101

 

먼저 Volley 라이브러리를 사용하여 데이터를 받아오는 과정에 대한 설명은 아래 글을 참고하자.

https://ju-hy.tistory.com/66

 

Volley 사용법

Volley란? 앱에서 서버와 http 통신을 할 때 HttpURLConnection을 사용하면 직접 요청과 응답을 받는 것이 가능하다. 하지만 직접 쓰레드를 구현해야 하며, 기본적인 코드 양 또한 많아 코드가 복잡해진다는 단점..

ju-hy.tistory.com

 

implementation 'com.google.code.gson:gson:2.8.5'

첫번째로 build.gradle에서 dependencies에 Gson 라이브러리를 추가해주자.

 

다음으로 데이터의 형태를 분석하여 클래스를 정의해보자.

Gson 라이브러리는 Json 문자열을 객체로 변환해주는 기능을 지원한다.

미리 데이터에 맞게 클래스를 정의해놓으면 한번에 문자열을 객체로 전환할 수 있다.

 

영화관입장권통합전산망 open api에서 받는 데이터는 위와 같은 형태이다.

boxOfficeResult 객체 안에 boxofficeType 정보, showRange 정보, dailyBoxOfficeList 라는 배열이 있다.

그리고 dailyBoxOfficeList 배열 안에는 영화의 정보들을 담고 있는 객체들이 있다.

 

이를 바탕으로 클래스를 구성해보자.

 

package com.juhy.myapplication;

public class MovieList {
    MovieListResult boxOfficeResult;
}
package com.juhy.myapplication;

import java.util.ArrayList;

public class MovieListResult {
    String boxofficeType;
    String showRange;
    ArrayList<MovieListItem> dailyBoxOfficeList = new ArrayList<MovieListItem>();
}
package com.juhy.myapplication;

public class MovieListItem {
    String rnum;
    String rank;
    String rankInten;
    String rankOldAndNew;
    String movieCd;
    String movieNm;
    String openDt;
    String salesAmt;
    String salesShare;
    String salesInten;
    String salesChange;
    String salesAcc;
    String audiCnt;
    String audiInten;
    String audiChange;
    String audiAcc;
    String scrnCnt;
    String showCnt;
}

앞서 설명한 구조대로 클래스를 정의해주었다.

이 때 key값과 멤버변수의 변수명을 동일하게 구성해주어야 Gson을 통해 변환이 가능하다.

 

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    EditText editText;
    TextView textView;

    String url = "https://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=430156241533f1d058c603178cc3ca0e&targetDt=20120101";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = findViewById(R.id.editText);
        textView = findViewById(R.id.textView);

        editText.setText(url);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendRequest();
            }
        });

        if(AppHelper.requestQueue == null)
            AppHelper.requestQueue = Volley.newRequestQueue(getApplicationContext());

    }

    public void sendRequest() {

        StringRequest request = new StringRequest(
                Request.Method.GET,
                url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        textView.setText(response);

                        parseResponse(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        textView.setText(error.getMessage());
                    }
                }
        ) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                //params.put("key", "value");
                return params;
            }
        };

        // 이전 결과가 있더라도 새로 요청
        request.setShouldCache(false);

        AppHelper.requestQueue.add(request);
    }

    public void parseResponse(String response){
        Gson gson = new Gson();
        MovieList movieList = gson.fromJson(response, MovieList.class);

        if(movieList != null){
            int cnt = movieList.boxOfficeResult.dailyBoxOfficeList.size();
            Toast.makeText(getApplicationContext(), cnt + " movies found", Toast.LENGTH_SHORT).show();
        }
    }

}

서버로부터 응답이 들어오면 응답을 받아와 parseResponse() 함수에 넘겨준다.

 

parseResponse()에서는 먼저 데이터 변환을 위한 Gson 객체를 만들어준다.

그리고 Gson 객체의 fromJson() 함수에 응답받은 String과 최상위 객체의 클래스를 넘겨주면,

Gson 라이브러리에서 넘겨준 클래스 형태로 String을 변환하여 넘겨준다.

 

마지막으로 변환된 MovieList 객체를 통해 몇 개의 영화를 받았는지 Toast로 띄워주었다.

 

 

api로부터 넘겨받은 Json String을 정상적으로 변환하여 10개의 영화 목록이 수신된 것을 볼 수 있다.

 

 

Reference

[부스트코스]안드로이드 프로그래밍

https://www.edwith.org/boostcourse-android