일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- ANR이란
- rxjava disposable
- 2022 플러터 설치
- android retrofit login
- 안드로이드 라이선스 종류
- 안드로이드 레트로핏 crud
- 자바 다형성
- 객체
- 안드로이드 레트로핏 사용법
- jvm이란
- 2022 플러터 안드로이드 스튜디오
- 큐 자바 코드
- 안드로이드 라이선스
- jvm 작동 원리
- 서비스 쓰레드 차이
- android ar 개발
- 안드로이드 유닛테스트란
- 멤버변수
- 플러터 설치 2022
- rxjava hot observable
- 안드로이드 유닛 테스트
- Rxjava Observable
- 클래스
- 서비스 vs 쓰레드
- 안드로이드 유닛 테스트 예시
- 안드로이드 os 구조
- rxjava cold observable
- 스택 큐 차이
- 스택 자바 코드
- ar vr 차이
- Today
- Total
나만을 위한 블로그
[Android] Gson이란? Gson 사용법 본문
서버에서 API를 통해 JSON 값들을 내려받으면 클라이언트인 안드로이드는 이를 파싱해서 필요한 곳에 알맞게 값들을 넣어주거나 표시해야 한다.
그러나 매번 JSONObject, JSONArray를 일일이 선언해서 파싱할 수는 없다. 귀찮다.
이 귀찮음을 해소하기 위해 존재하는 라이브러리가 바로 Gson이라는 라이브러리다. 이걸 쓰면 귀찮아서 숨 넘어갈 것 같은 JSON 파싱 과정을 매우 많이 단축시켜준다.
주의할 것은 JSON 파싱을 수작업으로 해본 적 없이 이 라이브러리를 먼저 사용하지 않는 것이다. 최소한 내가 받은 JSON이 어떤 구조인지 대충 짐작할 수 있고 로직이 어찌저찌 생각나는 정도가 되고 나서야 사용하면 좋다. 단순한 구조의 JSON이라면 Gson을 쓰는 것보다 수작업으로 파싱 때리는 게 더 나을 수도 있다.
각설하고, 먼저 Gson이란 무엇인지부터 알아보자. 구글에 검색해보면 공식 사이트처럼 보이는 곳이 몇 곳 있다.
https://github.com/google/gson
Gson은 자바 객체를 JSON 표현으로 변환하는 데 사용할 수 있는 자바 라이브러리다. JSON 문자열을 동등한 자바 객체로 변환하는 데에도 사용할 수 있다. Gson은 소스코드가 없는 기존 객체를 포함해 임의의 자바 객체로 작업할 수 있다. 자바 객체를 JSON 변환할 수 있는 몇 가지 오픈소스 프로젝트가 있다. 그러나 대부분은 클래스에 자바 어노테이션을 배치해야 한다. 또한 대부분은 제네릭의 사용을 완전히 지원하지 않는다. Gson은 이 2가지 모두를 매우 중요한 디자인 목표로 간주한다.
정리하면 자바 객체 <-> JSON 변환할 때 사용할 수 있는 자바 라이브러리다. 메서드 설명에 좀 더 집중하는 자바독에선 Gson 클래스에 대해 아래와 같이 설명한다.
https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.0/com/google/gson/Gson.html
Gson은 일반적으로 먼저 Gson 인스턴스를 구성한 다음 toJson(Object) 또는 fromJson(String, Class)를 호출해 사용한다. Gson 인스턴스는 Thread-safe하므로 여러 쓰레드에서 자유롭게 재사용할 수 있다. 기본 구성이 필요한 모든 경우 new Gson()을 호출해 Gson 인스턴스를 만들 수 있다. GsonBuilder를 써서 버전 관리, 예쁜 인쇄, 사용자 지정 JsonSerializers, JsonDeserializers 및 InstanceCreators와 같은 다양한 구성 옵션으로 Gson 인스턴스를 빌드할 수도 있다.
Gson 객체를 만든 다음 toJson()과 fromJson()으로 JSON을 다루는 내용 같다. 이제 코드로 보자.
안드로이드 스튜디오를 사용한다면 먼저 아래의 의존성 문구를 앱 수준 gradle에 붙여넣는다. 레트로핏을 사용할 때 추가하는 의존성이다.
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
레트로핏과 상관없는 의존성은 아래와 같다. 위의 의존성이 작동하지 않는다면 이걸 써서 진행한다.
implementation 'com.google.code.gson:gson:2.9.0'
첫 번째 링크에 메이븐의 경우 어떻게 사용해야 하는지도 나와있으니 참고하자.
그 다음은 패키지명 옆에 (test)가 적힌 패키지 안에 테스트 파일을 작성하는 것이다. 에뮬레이터 없이도 실행이 가능하다.
import com.google.gson.Gson;
import org.junit.Before;
import org.junit.Test;
public class JsonTest {
String json;
Gson gson;
@Before
public void setBefore() {
json = "{\n" +
"\"name\":\"홍길동\",\n" +
"\"age\":14,\n" +
"\"height\":182.4,\n" +
"\"marriage\":false\n" +
"}";
gson = new Gson();
}
@Test
public void gsonTest() {
Person person = gson.fromJson(json, Person.class);
System.out.println("이름 : " + person.getName());
System.out.println("나이 : " + person.getAge());
System.out.println("키 : " + person.getHeight());
System.out.println("결혼 여부 : " + person.isMarriage());
}
}
여기선 json 변수 안에 담긴 값들을 하드코딩으로 때우지만 서버에서 레트로핏으로 값을 내려받는다면 response.body() 값을 담은 변수를 사용해도 된다.
다른 부분은 설명할 필요도 없으니 넘어가고 gsonTest() 안의 첫 코드를 보자.
gson.fromJson()의 첫 번째 매개변수로 String 형태의 JSON 값이 담긴 변수를 집어넣고, 그 다음으로 Person이란 클래스를 넣는다.
이 클래스는 아래와 같다.
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Person {
@SerializedName("name")
@Expose
private String personName;
@SerializedName("age")
@Expose
private int age;
@SerializedName("height")
@Expose
private double height;
@SerializedName("marriage")
@Expose
private boolean marriage;
public String getName() {
return personName;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public boolean isMarriage() {
return marriage;
}
}
값을 받아오기만 할 것이기 때문에 변수들과 getter가 있다. 중요한 것은 @SerializedName 이라는 어노테이션이다. 이 어노테이션은 어떤 역할을 하는 어노테이션일까?
https://howtodoinjava.com/gson/gson-serializedname/
기본적으로 자바 모델 클래스와 JSON이 정확히 같은 필드명을 사용한다고 가정한다. 그러나 때로는 그렇지 않고 특정 이름이 다르다. 그 때 @SerializedName 어노테이션이 도움 된다. @SerializedName 어노테이션은 제공된 이름 값을 사용해서 JSON으로 직렬화돼야 함을 나타낸다. 이 어노테이션은 GsonBuilder 클래스를 사용했을 수 있는 기본 필드 명명 정책을 포함해 모든 FieldNamePolicy를 재정의한다. 이 어노테이션에 지정하는 값은 유효한 JSON 필드명이어야 한다.
쉽게 말해서 내가 선언한 DTO 안의 변수명이 JSON 안의 이름과 다를 경우, 어노테이션 안에 적은 이름의 JSON 값을 가져오는 어노테이션이다.
@SerializedName 어노테이션이 무슨 일을 하는지 더 명확하게 알기 위해 일단 실행시켜보자. 그럼 콘솔에 아래와 같은 결과가 출력된다.
원하는 대로 잘 파싱됐다. 이제 Person에서 name 위의 @SerializedName 어노테이션을 없애고 다시 빌드해보자.
Person은 이런 형태가 돼야 한다.
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Person {
@Expose
private String personName;
@SerializedName("age")
@Expose
private int age;
@SerializedName("height")
@Expose
private double height;
@SerializedName("marriage")
@Expose
private boolean marriage;
public String getName() {
return personName;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public boolean isMarriage() {
return marriage;
}
}
이름을 받아오지 못하고 null이 출력된다. 그럼 age 위의 @SerializedName 어노테이션을 지워도 나이값을 받아오지 못하는 건가?
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Person {
@Expose
private String personName;
@Expose
private int age;
@SerializedName("height")
@Expose
private double height;
@SerializedName("marriage")
@Expose
private boolean marriage;
public String getName() {
return personName;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public boolean isMarriage() {
return marriage;
}
}
아니다. age위의 @SerializedName 어노테이션을 지워도 나이는 잘 받아온다.
이걸 보면 @SerializedName 어노테이션이 하는 일이 더 명확해진다. Gson이 Person.class 안에 있는 변수명과 일치하는 JSON 값을 가져오는데 @SerializedName 어노테이션이 없고 변수명이 JSONObject의 key와 다를 경우, 그것과 일치하는 값을 변수와 매핑하지 못해 null을 출력하는 것이다.
그러니 가급적이면 JSON과 일치하는 자료형과 이름으로 변수를 선언하는 게 좋다. 이제 Person 클래스를 원래 상태로 돌려보자. personName이란 변수명도 원래는 name 이었다.
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Person {
@SerializedName("name")
@Expose
private String name;
@SerializedName("age")
@Expose
private int age;
@SerializedName("height")
@Expose
private double height;
@SerializedName("marriage")
@Expose
private boolean marriage;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getHeight() {
return height;
}
public boolean isMarriage() {
return marriage;
}
}
다시 실행하면 잘 파싱해온다. 이런 식으로 JSONArray도 파싱해오면 된다.
'Android' 카테고리의 다른 글
[Android] 맥북 M1 Pro에서 안드로이드 라이브러리(aar) 만드는 법 (with Kotlin) (0) | 2022.04.22 |
---|---|
[Android] 여러 체크박스들을 배열에 담아서 클릭 리스너 붙이는 법 (0) | 2022.03.31 |
[Android] espresso를 사용한 UI 테스트(+리사이클러뷰) (0) | 2022.02.07 |
[Android] 단위 테스트 시 static 메서드를 테스트하는 방법 (0) | 2022.02.06 |
[Android] 단위 테스트 시 쉐어드 프리퍼런스를 사용하는 방법 (0) | 2022.02.05 |