데이터 작업 시 자주 사용하는 JSON과 GSON, Jackson를 분석하여 정리해보겠다.
JSON
: 자바스크립트에서 사용하는 객체 표기법
https://developer.android.com/reference/org/json/package-summary?hl=en
org.json | Android Developers
android.net.wifi.hotspot2.omadm
developer.android.com
JSON은 네 종류의 Class, 한 종류의 Exception를 가지고 있다.
체감상 자주 사용하는 Class는 JSONObject와 JSONArray이며
주로 서버와 웹 또는 앱 간의 데이터 통신 시 사용하는 데이터 형식이다.
Key와 Value의 쌍으로 이루어진 형태이다.
*서버에서 받는 JSON 데이터를 파싱하는 법
우선 assets 폴더에 json 파일을 작성한다.
new -> File을 선택하면 된다.
assets/jsonData.json 을 작성했다.
{
"fruit": [
{
"name": "apple",
"color": [
"red",
"green",
"yellow"
]
},
{
"name": "banana",
"color": [
"yellow",
"green"
]
}
]
}
JSONPractice.java 파일을 생성했다.
- assets 폴더에 작성한 json 파일을 스트림으로 읽어와 String 객체에 저장한다.
- new JSONObject 를 통해 해당 String 객체를 JSONObject 객체로 변환한다.
- JSONObject 객체를 Parser 클래스로 보낸다.
import android.os.Bundle;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class JSONPractice extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String json = "";
try {
InputStream is = null;
is = getAssets().open("jsonData.json");
int fileSize = is.available();
byte[] buffer = new byte[fileSize];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
Log.d("json practice/ json text : ",json);
JSONPracticeParser parser = new JSONPracticeParser();
JSONObject jsonObject = new JSONObject(json);
parser.parseData(new FRUITData(),jsonObject);
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
}
JSONPracticeParser 파일을 생성했다.
해당 위치에서 JSONObject 객체를 읽어와 필드 별로 파싱할 것이다.
- 우선 json 데이터가 배열 형태이기 때문에
전달받은 JSONObject 객체에서 getJSONArray를 통해 array 형태로 추출한다.
- 파싱한 array를 저장할 ArrayList 또한 생성한다.
- 반복문을 통해 ArrayList에서 JSONObject를 차례로 읽어와 데이터 클래스에 저장한다.
(**JSONObject 안에 JSONObject가 있는 셈이다.
큰 JSONObject에서 JSONArray 추출 => JSONArray에서 여러개의 작은 JSONObject 추출**)
- 완성된 데이터 클래스의 객체는 ArrayList에 저장해둔다.
- 마지막으로 데이터 클래스에 완성된 ArrayList를 set 해주면 된다.
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class JSONPracticeParser {
public void parseData(FRUITData fruitData, JSONObject jsonObject) {
if(fruitData == null || jsonObject == null) {
return;
}
try {
JSONArray jsonArray = jsonObject.getJSONArray("fruit");
ArrayList<FRUITData.FruitItem> fruitItemArrayList = new ArrayList<FRUITData.FruitItem>();
for(int i=0; i<jsonArray.length(); i++){
FRUITData.FruitItem fruitItem = fruitData.getFruitItemInstance();
JSONObject object = jsonArray.getJSONObject(i);
if (!object.isNull("name")) {
String name = object.getString("name");
Log.d("json practice/ name : ",name);
fruitItem.setName(name);
}
if (!object.isNull("color")) {
String color = object.getString("color");
Log.d("json practice/ color : ",color);
fruitItem.setColor(color);
}
fruitItemArrayList.add(fruitItem);
}
fruitData.setFruitList(fruitItemArrayList);
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
필요한 데이터 클래스이다.
import java.util.ArrayList;
public class FRUITData {
private ArrayList<FruitItem> fruitList = new ArrayList<FruitItem>();
public ArrayList<FruitItem> getFruitList() {
return fruitList;
}
public void setFruitList(ArrayList<FruitItem> fruitList) {
this.fruitList = fruitList;
}
public class FruitItem{
private String name = null;
private String color = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public FruitItem getFruitItemInstance(){
FruitItem fruitItem = new FruitItem();
return fruitItem;
}
}
처음에 File로 작성한 json의 내용과 그 후 파싱한 데이터가 제대로 남겨지는 걸 확인할 수 있다.
이렇게 JSON 데이터를 활용하는 예시를 들어봤다.
GSON
: 구글에서 제공하는 JSON 라이브러리로, 주로 JSON 데이터를 JAVA 객체로 변환할 때 주로 사용한다.
자주 사용하는 메소드로는 fromJson, toJson이 있다.
#1 fromJson을 이용하여 JSONObject 객체를 JAVA 객체로 변환하기
우선 build.gradle의 dependencies에 추가해주어야 한다.
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}
위와는 다르게 단일 형태의 json 파일을 생성하였다.
jsonDataNotArray.json
{
"name": "apple",
"color": [
"red",
"green",
"yellow"
]
}
액티비티에서는 첫번째 예시와 다르게 json 데이터를 String 형식으로 전달하였다.
is = getAssets().open("jsonDataNotArray.json");
int fileSize = is.available();
byte[] buffer = new byte[fileSize];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
Log.d("json practice/ json text : ",json);
JSONPracticeParser parser = new JSONPracticeParser();
parser.parseDataFromGSON(json);
Parser 클래스에도 GSON을 활용하는 parse 메소드를 따로 작성했다.
public void parseDataFromGSON(String json){
Gson gson = new Gson();
FRUITData.FruitItemGSON fruitItem = gson.fromJson(json,FRUITData.FruitItemGSON.class);
Log.d("json practice/ name : ",fruitItem.getName());
for(int i=0; i<fruitItem.getColor().length; i++)
Log.d("json practice/ color : ",fruitItem.getColor()[i]);
}
여기서 주의할 점은 데이터 클래스를 수정해야 한다는 것이다.
문제가 되는 것은 color필드인데, 기존의 jsonObject.getString("color")를 했던 것과 달리
GSON을 활용하여 데이터를 추출할 경우에는 데이터 타입을 따로 정의할 수 없기 때문에
그대로 사용하면 아래와 같은 문제가 발생한다.
json 파일에 color필드는 사실 String[] 형태로 작성되어 있어서,
데이터 클래스에도 String[]으로 선언해두어야 이런 이슈를 피할 수 있다.
public class FruitItemGSON{
private String name = null;
private String[] color = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getColor() {
return color;
}
public void setColor(String[] color) {
this.color = color;
}
}
핵심 : GSON을 활용하여 데이터 작업을 할 때에는 JSON파일 내용과 데이터 형식이 꼭 일치해야 한다.
color 필드는 반복문을 활용하여 String 리스트의 값을 하나씩 출력한 것이다.
#2 toJson을 이용하여 JAVA 객체를 JSONObject 객체로 변환하기
기존 메소드에 gson.toJson을 이용해 한 줄만 추가로 작성하였다.
public void parseDataFromGSON(String json){
Gson gson = new Gson();
FRUITData.FruitItemGSON fruitItem = gson.fromJson(json,FRUITData.FruitItemGSON.class);
Log.d("json practice/ name : ",fruitItem.getName());
for(int i=0; i<fruitItem.getColor().length; i++)
Log.d("json practice/ color : ",fruitItem.getColor()[i]);
/**JAVA INSTANCE -> JSON INSTANCE*/
if(fruitItem!=null){
String jsonFromObject = gson.toJson(fruitItem);
Log.d("json practice/ JAVA INSTANCE -> JSON INSTANCE : ",jsonFromObject);
}
}
정상적으로 추출된 걸 확인할 수 있다.
위의 데이터 형식 이슈만 주의한다면 GSON을 활용하는 게 훨씬 작업하기는 편리한 것 같다.
Jackson
: 구글에서 제공하는 JSON 라이브러리로, 주로 JSON 데이터를 JAVA 객체로 변환할 때 주로 사용한다.
이외에도 XML/YAML/CSV 등 다양한 형식의 데이터 작업에 사용되며, 사용이 빠르다는 장점이 있음.
build.gradle에 의존성 추가
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-core:2.9.7'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.7'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.7'
}
#1 ObjectMapper.readValue를 이용하여 JSONObject 객체를 JAVA 객체로 변환하기
굉장히 쉽다.
이번에도 String 객체만 이용하여 데이터 파싱을 했지만, mapper를 이용하여
URL, File 방식으로도 데이터를 읽어올 수 있다.
public void parseDataFromJackson(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
FRUITData.FruitItemGSON fruitItem = mapper.readValue(json,FRUITData.FruitItemGSON.class);
Log.d("json practice/ name : ",fruitItem.getName());
for(int i=0; i<fruitItem.getColor().length; i++)
Log.d("json practice/ color : ",fruitItem.getColor()[i]);
}
매우 잘 됨
#2 ObjectMapper.writeValue를 이용하여 JAVA 객체를 JSONObject 객체로 변환하기
public void parseDataFromJackson(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
FRUITData.FruitItemGSON fruitItem = mapper.readValue(json,FRUITData.FruitItemGSON.class);
Log.d("json practice/ name : ",fruitItem.getName());
for(int i=0; i<fruitItem.getColor().length; i++)
Log.d("json practice/ color : ",fruitItem.getColor()[i]);
/**JAVA INSTANCE -> JSON INSTANCE*/
if(fruitItem!=null){
mapper.writeValue(new File("C:\\sample\\output.json"),fruitItem);
}
}
이것도 한 줄만 추가해서 쉽게 파일을 추출할 수 있었다.
Jackson 라이브러리는 다른 라이브러리들에 비해 활용할 수 있는 방향이 다양해보인다.
'JAVA > Android' 카테고리의 다른 글
[JAVA][Android] SpannableStringBuilder로 TextView의 일부에만 스타일 지정하기 (0) | 2022.08.05 |
---|---|
[JAVA][Android] Bundle로 클래스 객체 전달하기 (0) | 2022.07.26 |
[JAVA][Android] ActivityResultLauncher를 이용한 액티비티 간의 통신 (0) | 2022.07.20 |
[JAVA][Android] 데이터 직렬화 (Serialize) (0) | 2022.07.18 |
[JAVA][Android] 액티비티 종료 전 주요 데이터를 Bundle에 저장하여 재활용하기 (0) | 2022.06.21 |