-
JSON 라이브러리 Gson과 Jackson - Gson편Android/Json 2019. 6. 18. 13:38
앞서 jackson을 어떻게 사용해야 하는가에 대해서 탐구해 보았는데
이번은 gson에 대해서 탐구를 해보겠다
Gson
Site : https://github.com/google/gson
Gson은 Java Object를 JSON 표현으로 변환하는 데 사용할 수있는 Java 라이브러리
또한 JSON 문자열을 동등한 Java 객체로 변환하는 데 사용할 수 있다.
Gson은 소스 코드가없는 기존 오브젝트를 포함하여
임의의 Java 오브젝트에 대해 작업 할 수 있다.
Gradle Dependency
implementation 'com.google.code.gson:gson:2.8.5'
1. POJO ( Plain Old Java Object ) 생성
enum class Gender { Male, Female; } data class Person( val name: Name, val age: Int, val gender: Gender ) data class Name( val firstName: String, val lastName: String )
Jackson과 동일한 객체를 사용하였다.
2. Java Object -> Json
fun main() { val person = Person(Name("홍", "길동"), 20, Gender.Male) val json = Gson().toJson(person) println(json) }
[ 결과 ]
{"age":20,"gender":"Male","name":{"firstName":"홍","lastName":"길동"}}
기본적으로 Gson객체를 생성후 toJson 메서드를 사용하면된다.
Jackson과 다르게 field를 정렬된 상태로 출력을 시킨다.
[ Tip ] Json을 이쁘게 출력시키는 방법은 아래와 같이 코드를 작성
val gson = GsonBuilder().setPrettyPrinting().create()
gson.toJson(person)
{
"age": 20,
"gender": "Male",
"name": {
"firstName": "홍",
"lastName": "길동"
}
}
3. Json -> Java Object
fun main() { val json = "{\"age\":20,\"gender\":\"Male\",\"fullName\":{\"firstName\":\"홍\",\"lastName\":\"길동\"}}" val result = Gson().fromJson(json, Person::class.java) println(result) }
[ 결과 ]
Person(name=Name(firstName=홍, lastName=길동), age=20, gender=Male)
Jackson과 다르게 기본값을 주지 않았지만 잘 작동한다.
4. Annotation
속성을 서포트 해주는 어노테이션! 2가지가 있다.
★ @Expose
Serialize/Deserialize 시 제외시킬 프로퍼티를 지정 Jackson과 간단하게 아래와 같이 어노테이션을 붙혀주면 된다.data class Person( @Expose(serialize = false) val name: Name, val age: Int, val gender: Gender )
위의 코드로 예상을 하면 name의 직렬화를 false로 하였으니
역직렬화를 할 경우 name이 null이 나와야 할 것이다.{"age":20,"gender":"Male","name":{"firstName":"홍","lastName":"길동"}} Person(name=Name(firstName=홍, lastName=길동), age=20, gender=Male)
음..? 적용이 되지 않는다... 또 Jackson처럼 코틀린 때문에 그런가 싶었더니
Gson에 옵션을 추가 시켜주어야 한다고 한다.
val gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
gson 객체를 생성하고 excludeFieldsWithoutExposeAnnotation를 해주어야 한다.
다시 빌드를 해보면Serialize : {} DeSerialize : Person(name=null, age=0, gender=null)
이번엔 모든 프로퍼티가 직렬화가 되지 않았다..
알고보니 이녀석은 좀 까다로운놈!
아래의 표를 참고하자Code Serialize Deserialize @Expose(deserialize = false)
val name: NameYES NO @Expose
val name: NameYES YES @Expose(serialize = false)
val name: NameNO YES @Expose(serialize = false, deserialize = false)
val name: NameNO NO val name: Name
NO NO
[ 결과 ]{"age":20,"gender":"Male"} Person(name=null, age=20, gender=Male)
보다시피 이름과 나이가 기본값인 공백과 0으로 설정된 것을 볼 수 있다.
상황에 따라서 잘 설정하면 될것 같다.
★ SerializedName
Jackson의 JsonProperty와 같이
getter/setter 의 이름을 property 와 다른 이름을 사용할 수 있도록 설정
Database 를 자바 클래스로 매핑하는데 DB의 컬럼명이 알기 어려울 경우등에 유용하게 사용data class Person( @SerializedName("fullName") val name: Name = Name(), val age: Int = 0, val gender: Gender = Gender.Male )
작동을 시켜보지만 별다른 변경점이 없다...
코틀린 DataClass 때문인데.. 별도의 모듈을 적용시켜 주어야 한다.
아래와 같이 코드를 변경!val json = Gson().toJson(person) println(json)
[ 결과 ]
( 변경 전 ) : {"age":20,"gender":"Male","name":{"firstName":"홍","lastName":"길동"}}
( 변경 후 ) : {"age":20,"gender":"Male","fullName":{"firstName":"홍","lastName":"길동"}}
5. Custom Serializer/Deserialize
JsonSerializer/Deserializer
사실상 Json을 쉽게 작성하고자 만들어 진것이 Gson!
굳이 내가 만든 객체의 프로퍼티가 Primitive라면 커스텀을 만들 필요는 없다...
여기서는 Date라는 클래스에 대해서만 작성되었고
Date는 Parsing을 어떻게 하냐에 따라서 2019-06-18도 Date 2019.06.18도 Date이다
이러한 경우에만 커스텀을 만들어 주면 될 것 같다. 이하 Jackson 동일
직렬화class DateSerializer : JsonSerializer { @SuppressLint("SimpleDateFormat") val dateFormat = SimpleDateFormat("yyyy-MM-dd") override fun serialize(src: Date, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement { return JsonPrimitive(dateFormat.format(src)) } }
역 직렬화
class DateDeserializer : JsonDeserializer { @SuppressLint("SimpleDateFormat") val dateFormat = SimpleDateFormat("yyyy-MM-dd") override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): Date { return dateFormat.parse(json.asString) } }
등록
val gson = GsonBuilder() .registerTypeAdapter(Date::class.java, DateSerializer()) .registerTypeAdapter(Date::class.java, DateDeserializer()) .create()
Person 코드 변경
data class Person( val name: Name, val age: Int, val gender: Gender, val birth: Date )
실행
val birth = SimpleDateFormat("yyyy-MM-dd").parse("2019-06-18") val person = Person(Name("홍", "길동"), 20, Gender.Male, birth) val json = gson.toJson(person) val result = gson.fromJson(json, Person::class.java) println(json) println(result)
[ 결과 ]
D/gson: {"age":20,"birth":"2019-06-18","gender":"Male","name":{"firstName":"홍","lastName":"길동"}} D/gson: Person(name=Name(firstName=홍, lastName=길동), age=20, gender=Male, birth=Tue Jun 18 00:00:00 GMT+09:00 2019)
정상적으로 Date로 파싱되는 것을 볼 수 있다.
이로써 Gson도 끝났다.. 상황에 따라 Jackson을 쓰던 gson을 쓰면 될 것 같다.'Android > Json' 카테고리의 다른 글
JSON 라이브러리 Gson과 Jackson - Jackson 편 (0) 2019.06.16 JSON 어떤 라이브러리를 사용해야 할까? (0) 2019.06.16