[Android] 간단하게 Gson 살펴보기

Jay·2021년 1월 19일
0

Android

목록 보기
12/39
post-thumbnail

Gson ⁉️

  • JSON 데이터를 JAVA 객체로 변환 시켜주는 라이브러리.
  • JAVA 객체를 JSON 데이터로 변환 시켜주는 라이브러리.
  • [JSON 데이터 ↔️ JAVA 객체]

Gson의 목표라..?

  • Java 객체를 JSON으로 혹은 그 반대로 변환하기 쉬운 방법을 제공한다.
  • 기본에 수정 불가능한 객체를 JSON으로 혹은 JSON으로부터 변환이 가능하다.
  • 객체에 대한 사용자 정의 표현이 가능하다.
  • 어떠한 복합적인 객체도 지원한다.
  • 간결하고 읽기 쉬운 JSON을 생성한다.

Gson의 성능과 확장성

  • 문자열 : 25mb이상의 문자열을 역직렬화(객체화)하는데 이상 없음.
  • 대량의 컬렉션 : 140만개의 컬렉션 객체 직렬화/ 8만7천개의 컬렉션 객체 역직렬화 가능.

Usage

  • 주요 클래스는 Gson
  • new Gson()을 호출하여 Gson인스턴스 생성이 가능하다.
  • GsonBuilder라는 클래스를 사용하여 Gson 인스턴스를 여러가지 세팅 사용 생성하는데 가능하다.
  • Gson 인스턴스는 JSON연산자들이 호출되는 동안 어떠한 상태가 유지되지 않는다. 그래서 같은 인스턴스로 여러번 JSON 직렬화/역직렬화 연산을 하기 위해 다시 사용할 수 있다.

Sample

Basic

- Serializable
Gson gson = new Gson();
gson.toJson(1); // 1
gson.toJson("abcd"); //"abcd"
gson.toJson(new Long(10)); //10
int[] values = {1};
gson.toJson(values) // [1]


- Deserializable
int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1",Long.class);

Object

//
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;//transient는 직렬화를 하지않도록하는 키워드
  BagOfPrimitives() {
    // no-args constructor
  }
}

// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);  

//value3는 직렬화되지 않는다.
// ==> json is {"value1":1,"value2":"abc"}

무한 재귀 발생으로 순환 참조로 객체를 직렬화 할 수 없을 수 있다.

// 역 직렬화
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
// ==> obj2 is just like obj

📌 Object with Gson

  • private field를 사용하는 것이 좋다.
  • 직렬화 및 역직렬화 field가 포함되는 것을 나타내기 위해 주석을 사용할 필요는 없다.
  • field에 transient라고 표시한다면, 기본적으로 직렬화/역직렬화가 되지 않는다.
  • 반드시 null을 올바르게 처리해야 한다.
    • 직렬화 하는 동안, null field는 결과에서 사라진다.
    • 역직렬화 하는 동안, JSON 결과에서 없는 항목은 객체의 해당하는 필드를 기본값으로 설정한다.
  • 필드가 Synthetic인 경우, 직렬화/역직렬화 수행 되지 않음.
  • 내부 클래스, 익명 클래스 및 로컬 클래스에 해당하는 외부 클래스의 필드는 직렬화/ 역직렬화 되지 않는다.

Generic Type 직렬화/역직렬화

  • toJson(obj)를 호출할 때, Gson은 직렬화를 위해 field 정보를 얻으려고 obj.getClass() 를 호출하게 된다.
  • MyClass.class 객체를 fromJson(json, MyClass.class)메서드에서 전달할 수도 있다.
  • 이것은 객체가 non-generic type이기에 잘 동작한다.
    만약 객체가 generic type이라면 java type erasure에 의해 generic type의 정보는 사라진다.
class Foo<T> {
  T value;
}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // foo.value는 올바르게 직렬화되지 않습니다.

gson.fromJson(json, foo.getClass()); // foo.value를 Bar로 역직렬화하는데 실패합니다.

위의 코드는 값을 Bar Type으로 해석하는데 실패한다.
🤷 왜냐? Gson은 받은 객체의 클래스 정보를 얻기 위해 foo.getClass() 를 호출하는데, 이 메서드는 처리되지 않은 클래스인 Foo.class를 반환하기 때문이다.

generic type을 위한 올바른 매개변수용 type을 지정함으로 이 문제를 해결할 수 있다. 그러기 위해 TypeToken 클래스를 사용할 수 있다.

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);

gson.fromJson(json, fooType);

실제로 footype을 얻기위해 사용되는 idiom은 getType()메서드를 갖는 익명 로컬 inner 클래스를 정의한다. getType()메서드는 완전환 매개변수화된 type을 반환한다.


간단하게만 공식문서를 살펴보았는데 제대로 파고들면 쉽지 않을 것 같다.
꾸준히 개념 정리를 해야하는 부분이다.😅

Reference

profile
developer

0개의 댓글