Gson Basics

2017. 1. 31. 20:23

Overview


예제를 통해 case by case 사용법을 익혀보자. 

  • 기본형
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Serialization
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]
 
// Deserialization
int one = gson.fromJson("1"int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\""String.class);
String[] anotherStr = gson.fromJson("[\"abc\"]"String[].class);
  • Object형 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    // no-args constructor
  }
}
 
// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);  
// ==> json is {"value1":1,"value2":"abc"}
 
// Deserialization
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
// ==> obj2 is just like obj
    • private field도 된다. (annotation이 전혀 필요 없다)
    • transient 키워드가 있는 경우 제외한다. (transient가 serialization을 막는 키워드이므로)
    • Serialize할 때 null 값들은 skip 된다. 반대로 JSON에서 missing entry는 deserialize할 때 null로 대입된다. 
    • Inner class에 있는 outer class 대응 field, anonymous class, local class는 무시된다. 
  • Nested class
    • 일반적으로 nested inner class도 다 처리할 수 있는데 아래의 경우와 같이 inner class가 param이 없는 기본 생성자를 가지고 있을 경우 serialize가 안된다. (이유에 대한 설명이 이해 안됨)
1
2
3
4
5
6
7
8
9
10
11
12
public class A { 
  public String a; 
 
  class B { 
 
    public String b; 
 
    public B() {
      // No args constructor for B
    }
  } 
}
    • 이 경우 inner class 앞에 static 키워드를 붙여라. (아니면 특별한 instance creator를 정의하는 방법도 있는데 추천하진 않는다고 되어 있음) 
  • Array
1
2
3
4
5
6
7
8
9
10
11
Gson gson = new Gson();
int[] ints = {12345};
String[] strings = {"abc""def""ghi"};
 
// Serialization
gson.toJson(ints);     // ==> [1,2,3,4,5]
gson.toJson(strings);  // ==> ["abc", "def", "ghi"]
 
// Deserialization
int[] ints2 = gson.fromJson("[1,2,3,4,5]"int[].class); 
// ==> ints2 will be same as ints
    • Multi-dimension도 가능하다. 
  • Collections
1
2
3
4
5
6
7
8
9
10
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);
 
// Serialization
String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]
 
// Deserialization
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints 
    • Gson은 임의의 object에 대한 collection을 serialize할 수는 있지만 deserialize할 수는 없다. 따라서 위의 예제와 같이 Generic type을 사용한 collection에 대해 사용하여야 한다. 
    • 만약 임의의 Object에 대한 collection을 사용할 필요가 있다면 Gson parser API (low-level streaming parser / DOM parser를 제공)를 사용하든지, Collection.class를 위한 type adapter를 등록하든지, MyCollectionMemberType을 위한 adapter를 등록해서 Collection<MyCollectionMemberType>의 fromJson()을 사용하는 방법이 있다. (자세한 건 공식 가이드를 참고해라)
  • Generic
    • 아래와 같이 코드를 짜면 안된다. 
1
2
3
4
5
6
7
8
class Foo<T> {
  T value;
}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // May not serialize foo.value correctly
 
gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
    • Gson은 그냥 Foo.class라고 인식해버린다. 따라서 아래와 같이 작성해야 한다. 
1
2
3
4
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);
 
gson.fromJson(json, fooType);
  • Custom serializer and deserializer
    • Custom serializer/deserializer를 지원하는데 특히나 library class (예를 들어, DateTime)들을 다룰 때 유용하다. Gson은 이를 위해 Json Serializers, Json Deserializers, Instance Creators 인터페이스를 지원한다. 아래와 같이 인터페이스를 구현한 custom class들을 GsonBuilder에 등록하면 된다. 
1
2
3
4
5
GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(MyType2.classnew MyTypeAdapter());
gson.registerTypeAdapter(MyType.classnew MySerializer());
gson.registerTypeAdapter(MyType.classnew MyDeserializer());
gson.registerTypeAdapter(MyType.classnew MyInstanceCreator());
    • 아래는 DateTime에 대한 Serializer의 작성 예제이다. JsonSerializer를 implements 하였다. 
1
2
3
4
5
private class DateTimeSerializer implements JsonSerializer<DateTime> {
  public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(src.toString());
  }
}

    • 아래는 DateTime에 대한 Deserializer의 작성 예제이다. JsonDeserializer를 implements 하였다. 
1
2
3
4
5
6
private class DateTimeDeserializer implements JsonDeserializer<DateTime> {
  public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
    return new DateTime(json.getAsJsonPrimitive().getAsString());
  }
}

    • DateTime같은 concrete class 뿐 아니라 generic class에 대해서도 JsonSerializer, JsonDeserializer 등록 가능하다 (자세한 것은 역시 user manual 참조)
    • Instance Creators의 경우 기본 생성자 (no-args constructor)가 있거나 deserializer가 등록되어 있으면 만들 필요는 없다. 아래은 예제이다. 
1
2
3
4
5
private class MoneyInstanceCreator implements InstanceCreator<Money> {
  public Money createInstance(Type type) {
    return new Money("1000000", CurrencyCode.USD);
  }
}


Posted by 그레이트쪼
:
BLOG main image
What a Great World!!
개발자의 잡동사니 책상 by 그레이트쪼

공지사항

카테고리

분류 전체보기 (70)
자료구조와 알고리즘 (35)
Java & Android (16)
C & C++, 일반 (7)
디자인패턴 (7)
자유로운 이야기 (5)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

달력

«   2024/05   »
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 31
Total :
Today : Yesterday :