๋ฐํ์ฃผ์ : JSON
๋ฐํ์ผ์ : 2018-08-06 (์)
๋ฐํ์ : ์ก์์
[TOC]
๋ ๋๊น์ง ์๋๋ก์ด๋[์ค์ค์ ์ง์] : 22์ฅ ๋คํธ์ํฌ ํต์
์๋ฐ์์์ ๋คํธ์ํฌ ํต์ ์ HttpURLConnection ๊ฐ์ฒด๋ฅผ ํตํ ๋ฐฉ๋ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
- AndroidManifest.xml ํ์ผ์ INTERNET ๊ถํ์ ์ถ๊ฐํ๋ค.
<uses-permission android:name="android.permission.INTERNET"/>
- ์์ค๋ฅผ ์ฝ์ด์ค๋ ํด๋์ค ์์ฑ
์๋๋ก์ด๋์์๋ ์๋ฐ์ ๋ค๋ฅด๊ฒ ๋คํธ์ํฌ ํต์ ์ ๋ฐ๋์ ์์ ์ค๋ ๋์์ ์ํํด์ผ ํ๋ ์ ์ฝ์ด ์๋ค. ๋ฐ๋ผ์ ๋น๋๊ธฐ ๋คํธ์ํฌ ํต์ ์ ํ๋ AsycnTask ๋ฅผ ์์ฑํด์ผ ํ๋ค.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ์์ค๋ฅผ ํ์ธํ๊ณ ์ถ์ ์ฌ์ดํธ ์ฃผ์
new HttpAsyncTask().execute("http://[์ฃผ์]");
}
private static class HttpAsyncTask extends AsyncTask<String, void, String> {
@Override
protected String doInBackground(String... params) {
String result = null;
String strUrl = params[0];
try {
// URL ๊ฐ์ฒด ์์ฑ
URL url = new URL(strUrl);
// URL ์ ์ฐ๊ฒฐํ ๊ฐ์ฒด ์์ฑ
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET"); // GET ๋ฐฉ์ ํต์
connection.setDoOutput(true); // ์ฐ๊ธฐ ๋ชจ๋
connection.setDoInput(true); // ์ฝ๊ธฐ ๋ชจ๋
connection.setUseCaches(false); // ์บ์ ์ฌ์ฉ
connection.setDefaultUseCaches(false);
// ์
๋ ฅ ์คํธ๋ฆผ ์ด๊ธฐ
InputStream inputStream = connection.getInputStream();
// ๋ฌธ์์ด ์ ์ฅ ๊ฐ์ฒด
StringBuilder builder = new StringBuilder();
// UTF-8 ๋ฐฉ์์ผ๋ก ์
๋ ฅ๋ฐ์ ์คํธ๋ฆผ์ ์ฝ์ด๋ค์ด๋ ๋ฒํผ ๊ฐ์ฒด
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
// ํ ์ค์ฉ ๋ฌธ์์ด์ ์ฝ์ด๋ค์ด๊ธฐ
String line;
while ((line = reader.readLine()) != null) {
builder.append(line + "\n");
}
// ๊ฒฐ๊ณผ
result = builder.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (s != null) {
Log.d("HttpAsyncTask", s);
}
}
}
}
HttpURLConnection์ ์ฌ์ฉํ์ฌ GET ๋ฐฉ์์ผ๋ก ์์ค๋ฅผ ์ฝ์ด์ค๋ ๊ธฐ๋ณธ์ ์ธ ์ฝ๋์ด๋ค. GET ๋ฐฉ์์ผ๋ก ์น์ฌ์ดํธ์ ์ฝ๋๋ฅผ ์ฝ์ด๋ค์ฌ ๋ก๊ทธ๋ก ์ถ๋ ฅํ๋ ๊ฐ๋จํ ์ฝ๋์ง๋ง, ๊ฝค ๋ณต์กํด ๋ณด์ธ๋ค. ์ค์ ๋ก ์๋ฐ์ ๋คํธ์ํฌ API๋ ์ฌ์ฉํ๊ธฐ๊ฐ ๊ทธ๋ ๊ฒ ํธํ์ง๋ ์๋ค.
Http/1.1 ํต์ ์ ๋ฌธ์ ์ ์ค ํ๋๋ ์ฐ๊ฒฐ๋น ํ ๋ฒ์ ํ๋์ ์์ฒญ๊ณผ ์๋ต๋ง ํ์ฉํ๋ค๋ ์ ์ด๋ค. ์ฌ๋ฌ ์์ฒญ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๋ ค๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๋ค๋ฅธ ํด๋ผ์ด์ธํธ์์๋ ์ฌ๋ฌ ๊ฐ์ ์์ผ์ ์ด์ด์ผ ํ๋๋ฐ, ์ด๊ฒ์ ํด๋ผ์ด์ธํธ์์๋ ํฐ ๋ฌธ์ ๊ฐ ์๋์ง๋ง, ์๋ฒ ๊ด์ ์์๋ ์ฌ๊ฐํ ๋ฌธ์ ์ด๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ๊ตฌ๊ธ์ด HTTP ํ๋กํ ์ฝ ๊ฐ์ ์์ ์ ์์ํ์๊ณ , SPDY(์คํผ๋)๋ผ ๋ถ๋ฆฌ๋ ์๋ก์ด ํ๋กํ ์ฝ์ ๊ตฌํํ์๋ค. SPDY๋ HTTP/1.1์ ๋นํด ์๋นํ ์ฑ๋ฅ ํฅ์๊ณผ ํจ์จ์ฑ์ ๋ณด์ฌ์ฃผ์๊ณ , 2015๋ ํ์ค์ด ๋ HTTP/2์ ๊ธฐ๋ฐ์ด ๋๋ค. OkHttp๋ Square์ฌ์์ ๊ฐ๋ฐํ Http/2์ SPDY๋ฅผ ์ง์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
- build.gradleํ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ ์ถ๊ฐ
dependencies {
...
implementation 'com.squareup.okhttp3:okhttp:3.8.1'
}
- OKHttp ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ์์ค๋ฅผ ํ์ธํ๊ณ ์ถ์ ์ฌ์ดํธ ์ฃผ์
new HttpAsyncTask().execute("http://[์ฃผ์]");
}
private static class HttpAsyncTask extends AsyncTask<String, void, String> {
// OkHttp ํด๋ผ์ด์ธํธ
OkHttpClient client = new OkHttpClient();
@Override
protected String doInBackground(String... params) {
String result = null;
String strUrl = params[0];
try {
// ์์ฒญ
Request request = new Request.Builder()
.url(strUrl)
.build();
// ์๋ต
Response response = client.newCall(request).execute();
Log.d(TAG, "onCreate: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(String s){
super.onPostExecute(s);
if (s != null){
Log.d("HttpAsyncTask", s);
}
}
}
}
- ๋ก๊ทธ์บฃ์ ์์ค๊ฐ ํ์๋๋ ๊ฒ์ ํ์ธํ๋ค.
OKHttp์ ๋์ ๋ฐฉ์์ okHttpClient ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ newCall() ๋ฉ์๋์ ์์ฒญ ์ ๋ณด๋ฅผ Request ๊ฐ์ฒด๋ก ์ ์ํ์ฌ ์ ๋ฌํ๋ค. execute() ๋ฉ์๋๋ ๋๊ธฐ ๋ฐฉ์์ผ๋ก ๋คํธ์ํฌ์ ์ ์ํ๊ณ ๊ฒฐ๊ณผ๋ฅผ Response ๊ฐ์ฒด๋ก ์๋ต๋ฐ๋๋ค. ์๋ต์๋ Header์ Body ๋ฑ์ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์๋ค.
์ด์ฒ๋ผ OKHttp๋ ๊ฐ๋จํ๊ฒ GET/POST ๋ฐฉ์์ผ๋ก HTTP ํต์ ์ ์ํํ ์ ์๊ฒ ํด์ค๋ค. ๋๊ธฐ/๋น๋๊ธฐ ๋ฐฉ์์ ๋ชจ๋ ์ง์ํ๋ฉฐ, ์ฝ๋๋ ๊ฐ๊ฒฐํด์ง๋ค. ์๋๋ก์ด๋ 2.3 ์ด์์์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์๋ฐ SDK 7 ์ด์์์ ๋์ํ๋ค.
Json(Javascript Object Notation) : javascript ์ธ์ด์์ ์ฌ์ฉ๋๊ธฐ ์์ํ ๊ฒฝ๋ ๋ฐ์ดํฐ ๊ตํ ํ์
- ์์ ๊ฐ์ ํํ์ ๋ฐ์ดํฐ๋ฅผ Json์ด๋ผ๊ณ ํ๋ค.
- Json ํฌ๋งท์์ []๋ ๋ฐฐ์ด์ ๋ํ๋ด๋ฉฐ, {}๋ ๊ฐ์ฒด๋ฅผ ๋ํ๋ธ๋ค.
- ์๋ฃ๊ตฌ์กฐ์ Map๊ณผ ๊ฐ์ ๊ตฌ์กฐ์ด๋ค.
- ์๋๋ก์ด๋์์ JSON ๊ฐ์ฒด๋ฅผ ๋ค๋ฃจ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค.
- JSONObject JSON ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์ ์๋ ๊ฐ์ฒด
- JSONArray JSONObject๋ฅผ ์ฌ๋ฌ ๊ฐ ๋ด์ ์ ์๋ ๋ฆฌ์คํธ ๊ฐ์ฒด
- Json์ XML๊ณผ ๋๋ถ์ด ๋ฐ์ดํฐ ํ์์ผ๋ก ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๊ณ ์์ผ๋ฉฐ, XML๋ณด๋ค ๊ฐ๊ฒฐํ๊ณ ์ดํดํ๊ธฐ ์ฝ๋ค.
- Json์ ์ค์ ๋ฐ์ดํฐ์ ์ง์คํ๋ฏ๋ก ์ ์ก๋๋ ๋ฐ์ดํฐ์ ์ฉ๋์ด ์ ๋ค.
- ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํด์ ์ฌ์ฉํ๊ธฐ ํธํ ํ์ฑ๋ ๋น๊ต์ ์ฝ๋ค.
- ๋ชจ๋ธํด๋์ค ์์ฑ
public class Weather {
private String country;
private String weather;
private String temperature;
public Weather(String country, String weather, String temperature){
this.country = country;
this.weather = weather;
this.temperature = temperature;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Weather{");
sb.append("country='").append(country).append('\'');
sb.append(", weather=").append(weather).append('\'');
sb.append(", temperature=").append(temperature).append('\'');
sb.append('}');
return sb.toString();
}
}
- JSONObject ๋์ Weather ํด๋์ค๋ฅผ ์ด์ฉํ์ฌ ๋ ์จ ๋ฐ์ดํฐ ๋ค๋ฃจ๊ธฐ
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ์์ค๋ฅผ ํ์ธํ๊ณ ์ถ์ ์ฌ์ดํธ ์ฃผ์
new HttpAsyncTask().execute("http://[์ฃผ์]");
}
private class HttpAsyncTask extends AsyncTask<String, Void, List<Weather>> {
// OKHttp ํด๋ผ์ด์ธํธ
OKHttpClient client = new OKHttpClient();
@Override
protected List<Weather> doInBackground(String... params) {
List<Weather> weatherList = new ArrayList<>();
String strUrl = params[0];
try {
// ์์ฒญ
Request request = new Request.Builder()
.url(strUrl)
.build();
// ์๋ต
Response response = client.newCall(request).execute();
JSONArray jsonArray = new JSONArray(resonse.body().string());
for(int i = 0; l < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String country = jsonObject.getString("country");
String weather = jsonObject.getString("weather");
String temperature = jsonObject.getString("temperature");
Weather w = new Weather(country, weather, temperature);
weatherList.add(w);
}
Log.d(TAG, "onCreate : " + weatherList.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return weatherList;
}
@Override
protected void onPostExecute(List<Weather> weatherList) {
super.onPostExecute(weatherList);
if (weatherList != null) {
Log.d("HttpAsyncTask", weatherList.toString());
}
}
}
}
- Weather์ ๋ฆฌ์คํธ๋ฅผ ๋ด์ ์ ์๋ ์ด๋ํฐ๋ฅผ ์์ฑํ๊ณ , ์ด ์ด๋ํฐ๋ฅผ ๋ฆฌ์คํธ๋ทฐ์ ์ ๋ฌํ๋ค.
public class WeatherAdapter extends BaseAdapter {
private final List<Weather> mList;
public WeatherAdapter(List<Weather> list) {
mList = list;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_weather, parent, false);
holder = new ViewHolder();
holder.country = (TextView) convertView.findViewById(R.id.country_text);
holder.weather = (TextView) convertView.findViewById(R.id.weather_text);
holder.temperature = (TextView) convertView.findViewById(R.id.temperature_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Weather weather = (Weather) getItem(position);
holder.country.setText(weather.getCountry());
holder.weather.setText(weather.getWeather());
holder.temperature.setText(weather.gettemperature());
return convertView;
}
// ๋ทฐ ํ๋ ํจํด
static class ViewHolder {
TextView country;
TextView weather;
TextView temperature;
}
}
- HttpAsyncTask์ onPostExecute() ๋ฉ์๋์์ ๋ฆฌ์คํธ๋ทฐ๋ฅผ ์กฐ์ํ๊ธฐ ์ํด ์ฝ๋ ์์
... ์๋ต ...
@Override
protected void onPostExecute(List<Weather> weatherList){
super.onPostExecute(weatherList);
if (weatherList != null){
Log.d("HttpAsyncTask", weaterList.toString());
WeatherAdapter adapter = new WeatherAdapter(weatherList);
mWeaterListView.setAdapter(adapter);
}
}
... ์๋ต ...
}
Gson์ ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ JSON ๋ฐ์ดํฐ์ ์๋ฐ ์ค๋ธ์ ํธ๋ฅผ ์ํธ ๋ณํํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
-
์๋ฐ์์ JSON์ ๋ค๋ฃจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ทธ ์ธ์๋ Jackson, JSONIC ๋ฑ ๋ค์ํ๋ค.
-
Gson์ ๋ด๋ถ์ ์ผ๋ก ์๋ฐ์ ๋ฆฌํ๋์ ์ด๋ผ๋ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋๋ฐ, ๋ฆฌํ๋์ ์ ์คํ์๊ฐ ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ธฐ๋ฒ์ด๋ฏ๋ก ์คํ์๊ฐ์ ๋ฏผ๊ฐํ ์ฑ์ ๊ฐ๋ฐํ ๋๋ ์ ํฉํ์ง ์๋ค.
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ ์ถ๊ฐ
dependencies {
... ์๋ต ...
implementation 'com.google.code.gson:gson:2.8.1'
}
- MainActivity.java ํ์ผ ๋ด์ HttpAsyncTask ํด๋์ค์์ JSON ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ๋ ๋ถ๋ถ์ Gson์ผ๋ก ์์
private static class HttpAsyncTask extends AsyncTask<String, void, List<Weather>> {
// OkHttp ํด๋ผ์ด์ธํธ
OkHttpClient client = new OkHttpClient();
@Override
protected String doInBackground(String... params) {
// JSON ๋ฐ์ดํฐ๊ฐ ๋ณํ ๋ ๊ฐ์ฒด
List<Weather> weatherList = new ArrayList<>();
String strUrl = params[0];
try {
// ์์ฒญ
Request request = new Request.Builder()
.url(strUrl)
.build();
// ์๋ต
Response response = client.newCall(request).execute();
Gson gson = new Gson();
// Gson ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ด๋ฌํ ๋ฆฌ์คํธ ํ์
์ ์๋์ผ๋ก ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํํ๋ ค๋ฉด
// ํ์
๊ฐ์ฒด๋ฅผ ์ง์ ํด ์ค์ผ ํ๋ค. Type ํด๋์ค๋ ์ฌ๋ฌ ํจํค์ง์ ์๋ ๋ฐ ๊ทธ ์ค
// import java.lang.reflect.Type์ ์ฌ์ฉํด์ผ ํ๋ค.
Type listType = new TypeToken<ArrayList<Weather>>() {}.getType();
// Type์ fromJson() ๋ฉ์๋์ ํจ๊ป ์ ๋ฌํ๋ฉด ์๋์ผ๋ก ๋ณํ๋๋ค.
weatherList = gson.fromJson(response.body().string(), listType);
Log.d(TAG, "onCreate: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
... ์๋ต ...
}
Retrofit ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ด๋ถ์ ์ผ๋ก๋ OKHttp๋ฅผ ์ฌ์ฉํ๋ฉด์ Gson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฒฐํฉํ์ฌ ๋ชจ๋ธ ํด๋์ค๋ List<๋ชจ๋ธ> ํํ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
- build.gradle ํ์ผ์ ์ข ์์ฑ ์ถ๊ฐ
dependencies {
... ์๋ต ...
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
}
- ์ธํฐํ์ด์ค ์์ฑ
์ด ํด๋์ค๋ค์ ํ์ด์ค๋ถ๊ณผ ๊ฐ์ SNS์ ์ฌ๋ฆฌ๋ ๊ธ๊ณผ ์ฌ์ฉ์, ๋๊ธ์ ํํํ๋ค.
Post๋ User์ Comment์ List๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ๋ณธ ์์ ๋ ์์ค๋ฅผ ๊ฐ๋จํ๊ฒ ๋ณด์ด๊ณ ์ getter์ setter๋ฅผ ์๋ตํ๊ณ ํ๋์ ๋ฉค๋ฒ ๋ณ์๋ค์ public์ผ๋ก ์ ์ธํ์๋ค.
- ์ฌ์ฉ์ ํด๋์ค
public class User {
public String email;
public String fullname;
public User(String email, String fullname){
this.email = email;
this.fullname = fullname;
}
}
- ํฌ์คํธ ํด๋์ค
public class Post {
public String title;
public String content;
public User author;
public List<Comment> comments;
public Post(User author, String title, String content) {
this.comments = new ArrayList<Comment>();
this.author = author;
this.title = title;
this.content = content;
}
}
- ๋๊ธ ํด๋์ค
public class Comment {
public String author;
public String content;
public Comment(String author, String content){
this.author = author;
this.content = content;
}
}
- ๋ชจ๋ธ ํด๋์ค๋ฅผ JSON์ผ๋ก ๋ณํ
์๋ฐ๋ก๋ถํฐ JSON์ผ๋ก ๋ณํํ ๋ toJson() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก null์ธ ํ๋๋ JSON์ ํฌํจ๋์ง ์๋๋ค.
public class ToJsonSample {
public static void main(String[] args) {
Gson gson = new Gson();
User user1 = new User("[email protected]", null); // fullname์ null์ ์ค์
User user2 = new User("[email protected]", "jeff");
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
// Java ๊ฐ์ฒด๋ก๋ถํฐ JSON์ผ๋ก ๋ณํ
System.out.println("์ฌ์ฉ์ : " + gson.toJson(user1));
// Java ๊ฐ์ฒด๋ก๋ถํฐ JSON์ผ๋ก ๋ณํ : List
System.out.println("์ฌ์ฉ์ ๋ชฉ๋ก : " + gson.toJson(userList));
Post newPost = new Post(userList.get(0), "PostTitle", "postContent");
Comment comment = new Comment("comment_author", "comment_comment");
newPost.comments.add(comment);
newPost.comments.add(comment);
// Java ๊ฐ์ฒด๋ก๋ถํฐ JSON์ผ๋ก ๋ณํ : ํ๋์ List๋ฅผ ํฌํจํ๋ ๊ฐ์ฒด
System.out.println("๋๊ธ์ ํฌํจํ ์ ๊ธ : " + gson.toJson(newPost));
}
}
- JSON์ ๋ชจ๋ธ ํด๋์ค๋ก ๋ณํ
JSON์ ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํํ ๋๋ fromJson() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.