SlideShare a Scribd company logo
kotlinx.
serialization
Arawn Park
SpringRunner
객체를 네트워크를 통해 전송하거나 데이터베이스 또는 파일에 저장할 수 있는 형식으로 변환하는 프로세스
!
직렬화serialization
!
자바 생태계의 직렬화 도구를 이용한 JSON 직렬화하기
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
class GsonSpec : FunSpec({
val gson = Gson()
test("객체를 JSON으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = gson.toJson(data)
serialized shouldBe """{"title":"foo","director":"x","rating":0.1}"""
val deserialized = gson.fromJson(serialized, Movie::class.java)
deserialized shouldBe data
}
test("리스트를 JSON으로 직렬화 또는 역직렬화하기") {
val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9))
val serialized = gson.toJson(data)
serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]"""
val javaType = object : TypeToken<List<Movie>>() {}.type
val deserialized = gson.fromJson<List<Movie>>(serialized, javaType)
deserialized shouldBe data
}
})
Kotlin/JVM
!
kotlinx.serialization으로 JSON 직렬화하기
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString
class SimpleKotlinSerializationSpec : FunSpec({
test("객체를 JSON으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = Json.encodeToString(data)
serialized shouldBe """{"title":"foo","director":"x","rating":0.1}"""
val deserialized = Json.decodeFromString<Movie>(serialized)
deserialized shouldBe data
}
test("리스트를 JSON으로 직렬화 또는 역직렬화하기") {
val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9))
val serialized = Json.encodeToString(data)
serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]"""
val deserialized = Json.decodeFromString<List<Movie>>(serialized)
deserialized shouldBe data
}
})
Kotlin/JVM
2017.07: kotlinx.serialization 프로젝트 시작
2017.09: 0.1 공개 (with Kotlin 1.1)
2020.10: 1.0 발표 (with Kotlin 1.4)
2022.05: 1.3 (with 1.4+)
.
.
.
왜 코틀린은 직렬화 도구를 직접 만들었을까?
!
null이 없었는데요 있었습니다
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
class GsonSpec : FunSpec({
val gson = Gson()
test("역직렬화시 널을 허용하지 않는 속성에 널을 입력해도 예외가 발생하지 않아요") {
val serialized = """{"title":"foo","rating":null}"""
val javaType = object : TypeToken<Movie>() {}.type
val deserialized = gson.fromJson<Movie>(serialized, javaType)
deserialized.title shouldBe "foo"
deserialized.director shouldBe null
deserialized.rating shouldBe 0.0
}
})
data class Movie(
val title: String,
val director: String,
val rating: Double = 1.0
)
Kotlin/JVM
!
기본이 안 돼 있네 기본이
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
class GsonSpec : FunSpec({
val gson = Gson()
test("역직렬화시 기본 인자가 설정된 속성을 지원하지 않아요") {
val serialized = """{"title":"foo","director":"x"}"""
val deserialized = gson.fromJson(serialized, Movie::class.java)
deserialized.rating shouldBe 0.0
}
})
data class Movie(
val title: String,
val director: String,
val rating: Double = 1.0
)
Kotlin/JVM
!
거 참 말 많네
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
class JacksonSpec : FunSpec({
test("데이터 클래스를 JSON으로 직렬화 또는 역직렬화하기") {
val mapper = JsonMapper.builder().build()
val data = Project("foo", 1.0)
val serialized = mapper.writeValueAsString(data)
serialized shouldBe """{"name":"foo","version":1.0}"""
val deserialized = mapper.readValue(serialized, Project::class.java)
deserialized.name shouldBe data.name
deserialized.version shouldBe data.version
}
})
data class Project @JsonCreator constructor(
@JsonProperty("name") val name: String,
@JsonProperty("version") val version: Double
)
Kotlin/JVM
!
거 참 말 많네 second edition
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.module.kotlin.kotlinModule
class JacksonSpec : FunSpec({
val mapper = JsonMapper.builder().addModule(kotlinModule()).build()
test("객체를 JSON으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = mapper.writeValueAsString(data)
serialized shouldBe """{"title":"foo","director":"x","rating":0.1}"""
val javaType = object: TypeReference<Movie>() {}
val deserialized = mapper.readValue(serialized, javaType)
deserialized shouldBe data
}
test("리스트를 JSON으로 직렬화 또는 역직렬화하기") {
val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9))
val serialized = mapper.writeValueAsString(data)
serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]"""
val javaType = mapper.typeFactory.constructCollectionType(List::class.java, Movie::class.java)
val deserialized = mapper.readValue<List<Movie>>(serialized, javaType)
deserialized shouldBe data
}
})
Kotlin/JVM
!
우린 너희만 있으면 돼
Browser Native
JVM Android
}
kotlinx.serialization 알아보기
!
kotlinx.serialization으로 JSON 직렬화하기
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
class SimpleKotlinSerializationSpec : FunSpec({
test("객체를 JSON으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = Json.encodeToString(Movie.serializer(), data)
serialized shouldBe """{"title":"foo","director":"x","rating":0.1}"""
val deserialized = Json.decodeFromString(Movie.serializer(), serialized)
deserialized shouldBe data
}
})
@Serializable
data class Movie(
val title: String,
val director: String,
val rating: Double = 1.0
)
Kotlin/JVM
!
컴파일 안전 보장 compile-time safe
import kotlinx.serialization.Serializable
class SimpleKotlinSerializationSpec : FunSpec({
test("컴파일 타임에 직렬화 지원 여부를 확인해요") {
data class User(val userName: String)
@Serializable
data class Project(
val name: String,
val owner: User,
val language: String = "Kotlin"
)
}
})
Kotlin/JVM
!
명료함 및 간결함 explicit and concise
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString
class SimpleKotlinSerializationSpec : FunSpec({
test("객체를 JSON으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = Json.encodeToString(data)
serialized shouldBe """{"title":"foo","director":"x","rating":0.1}"""
val deserialized = Json.decodeFromString<Movie>(serialized)
deserialized shouldBe data
}
test("리스트를 JSON으로 직렬화 또는 역직렬화하기") {
val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9))
val serialized = Json.encodeToString(data)
serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]"""
val deserialized = Json.decodeFromString<List<Movie>>(serialized)
deserialized shouldBe data
}
})
Kotlin/JVM
!
코틀린 지향 Kotlin-oriented
class SimpleKotlinSerializationSpec : FunSpec({
test("역직렬화시 널을 허용하지 않는 원시타입 속성에 널을 입력되면 예외가 발생해요") {
val exception = shouldThrow<SerializationException> {
Json.decodeFromString<Movie>("""{"title":"foo","director":"x","rating":null}""")
}
exception.message shouldBe """
Unexpected JSON token at offset 43: Failed to parse type 'double' for input 'null'
JSON input: {"title":"foo","director":"x","rating":null}
""".trimIndent()
}
test("역직렬화시 널을 허용하지 않는 속성에 널이 입력되면 예외가 발생해요") {
val exception = shouldThrow<SerializationException> {
Json.decodeFromString<Movie>("""{"title":"foo","rating":0.1}""")
}
exception.message shouldBe """
Field 'director' is required for type with serial name 'Movie', but it was missing
""".trimIndent()
}
test("역직렬화시 기본 인자가 설정된 속성을 지원해요") {
val deserialized = Json.decodeFromString<Movie>("""{"title":"foo","director":"x"}""")
deserialized.rating shouldBe 1.0
}
})
Kotlin/JVM
!
다양한 형식 지원 multi-format
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.decodeFromByteArray
class SimpleKotlinSerializationSpec : FunSpec({
test("객체를 CBOR 형식으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = Cbor.encodeToByteArray(data)
serialized.toAsciiHexString() shouldBe """
{BF}etitlecfoohdirectoraxfrating{FB}?{B9}{99}{99}{99}{99}{99}{9A}{FF}
""".trimIndent()
val deserialized = Cbor.decodeFromByteArray<Movie>(serialized)
deserialized shouldBe data
}
test("객체를 ProtoBuf 형식으로 직렬화 또는 역직렬화하기") {
val data = Movie("foo", "x", 0.1)
val serialized = ProtoBuf.encodeToByteArray(data)
serialized.toAsciiHexString() shouldBe """
{0A}{03}foo{12}{01}x{19}{9A}{99}{99}{99}{99}{99}{B9}?
""".trimIndent()
val deserialized = ProtoBuf.decodeFromByteArray<Movie>(serialized)
deserialized shouldBe data
}
})
Kotlin/JVM
!
멀티플랫폼 지원 multiplatform
JVM Android Browser Native
}
!
못다한 이야기...
멀티플랫폼 지원, 좀 더 가까이서 살펴보기
!
코틀린 멀티플랫폼 Kotlin Multiplatform
!
멀티플랫폼 프로젝트
!
모든 플랫폼에 공유할 로직 작성하기
Com
m
on
Kotlin
!
JS 플랫폼에서 사용할 로직 작성하기
Com
m
on
Kotlin
Kotlin/JS
!
멀티플랫폼 프로젝트 빌드하기
❯ ./gradlew clean build
Starting Build
Settings evaluated using settings file 'kotlinx-serialization/settings.gradle.kts'.
Projects loaded. Root project using build file 'kotlinx-serialization/build.gradle.kts'.

Included projects: [root project 'kotlinx-serialization']



> Task :kotlinNodeJsSetup
> Task :kotlinYarnSetup
> Task :kotlinNpmInstall
> Task :kotlinStoreYarnLock
> Task :compileKotlinJs
> Task :compileTestKotlinJs
> Task :jsTest
> Task :build



BUILD SUCCESSFUL in 1m 13s
51 actionable tasks: 45 executed, 6 up-to-date
❯ ls build/libs
kotlinx-serialization-js.klib
kotlinx-serialization-jvm.jar


❯ ls build/distributions
kotlinx-serialization.js
kotlinx-serialization.js.map
!
Kotlin/JS로 작성된 모듈을 브라우저에서 사용하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>kotlinx-serialization</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
<script>
require(["/assets/js/kotlinx-serialization.js"], function(serialization) {
const movies = serialization.Movies
const movie = movies.fromJson('{"title":"foo","director":"x","rating":0.1}')
console.log(`Movie (title: ${movie.title}, ...)`);
});
</script>
</body>
</html>
// file:src/jsMain/kotlin/Movies.kt
object Movies {
fun fromJson(content: String) = {..}
fun fromJsonArray(content: String) = {..}
}
!
Kotlin/JS로 작성된 모듈을 Node.js에서 사용하기
const serialization = require("./modules/kotlinx-serialization.js")
const movies = serialization.Movies
const movie = movies.fromJson('{"title":"foo","director":"x","rating":0.1}')
console.log(`Movie (title: ${movie.title}, ...)`);
// file:src/jsMain/kotlin/Movies.kt
object Movies {
fun fromJson(content: String) = {..}
fun fromJsonArray(content: String) = {..}
}
!
하나의 소스로 어디든 실행 할 수 있..어요?
잠시
삼천포로
빠질게요
https://www.flickr.com/photos/revilla/515323987
나는 왜 코틀린 직렬화를 사용했나
!
우리에겐 객체 캐싱이 필요해-
" #
$
!
애플리케이션 핵심 코드를 구현 기술로부터 지켜라!
애플리케이션
핵심 코드
}
!
언어가 제공하는 도구는 침투적인 기술일까? 아닐까?
애플리케이션
핵심 코드
}kotlinx.
serialization
end.
!
reference

More Related Content

PDF
Jpa 잘 (하는 척) 하기
PDF
자바에서 null을 안전하게 다루는 방법
PPTX
Flyweight Design Pattern
PPTX
Introduction to Koltin for Android Part I
PPTX
Angular 6 Form Validation with Material
PPTX
Practical non blocking microservices in java 8
PDF
Try Jetpack Compose
PDF
Py.test
Jpa 잘 (하는 척) 하기
자바에서 null을 안전하게 다루는 방법
Flyweight Design Pattern
Introduction to Koltin for Android Part I
Angular 6 Form Validation with Material
Practical non blocking microservices in java 8
Try Jetpack Compose
Py.test

What's hot (20)

PPSX
Formation JAVA/J2EE
PPTX
Jetpack Compose.pptx
PDF
Cours design pattern m youssfi partie 6 proxy
PDF
Correction Examen 2016-2017 POO .pdf
PDF
Django congress jp 2019 make query great again! (slide share)
PPT
Advanced JavaScript
PPTX
REST API 설계
PPTX
Kotlin InDepth Tutorial for beginners 2022
PDF
Spring Meetup Paris - Back to the basics of Spring (Boot)
PDF
Angular 2 overview in 60 minutes
PDF
Java 8-streams-collectors-patterns
PDF
Kotlin Coroutines and Android sitting in a tree
PDF
Docker + Kubernetes를 이용한 빌드 서버 가상화 사례
PDF
Django in Production
PDF
TypeScript: coding JavaScript without the pain
PDF
새해 일어난 일
PDF
C++20에서 리플렉션 기능 구현
PPT
Core java concepts
PDF
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
PPTX
Sharing Data Between Angular Components
Formation JAVA/J2EE
Jetpack Compose.pptx
Cours design pattern m youssfi partie 6 proxy
Correction Examen 2016-2017 POO .pdf
Django congress jp 2019 make query great again! (slide share)
Advanced JavaScript
REST API 설계
Kotlin InDepth Tutorial for beginners 2022
Spring Meetup Paris - Back to the basics of Spring (Boot)
Angular 2 overview in 60 minutes
Java 8-streams-collectors-patterns
Kotlin Coroutines and Android sitting in a tree
Docker + Kubernetes를 이용한 빌드 서버 가상화 사례
Django in Production
TypeScript: coding JavaScript without the pain
새해 일어난 일
C++20에서 리플렉션 기능 구현
Core java concepts
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
Sharing Data Between Angular Components
Ad

More from Arawn Park (17)

PDF
우린 같은 곳을 바라 보고 있나요?
PDF
코틀린 멀티플랫폼, 미지와의 조우
PDF
#살아있다 #자프링외길12년차 #코프링2개월생존기
PDF
우아한 모노리스
PDF
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
PDF
점진적인 레거시 웹 애플리케이션 개선 과정
PDF
이벤트 기반 분산 시스템을 향한 여정
PDF
Introduction to Kotlin
PDF
Reactive Web - Servlet & Async, Non-blocking I/O
PDF
Spring framework 4.x
PDF
씹고 뜯고 맛보고 즐기는 스트림 API
PDF
Spring framework 3.2 > 4.0 — themes and trends
PDF
overview of spring4
PDF
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
PDF
Resource Handling in Spring MVC
PDF
[Spring Camp 2013] Java Configuration 없인 못살아!
PDF
Vagrant와 chef로 개발서버 구축 자동화하기
우린 같은 곳을 바라 보고 있나요?
코틀린 멀티플랫폼, 미지와의 조우
#살아있다 #자프링외길12년차 #코프링2개월생존기
우아한 모노리스
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
점진적인 레거시 웹 애플리케이션 개선 과정
이벤트 기반 분산 시스템을 향한 여정
Introduction to Kotlin
Reactive Web - Servlet & Async, Non-blocking I/O
Spring framework 4.x
씹고 뜯고 맛보고 즐기는 스트림 API
Spring framework 3.2 > 4.0 — themes and trends
overview of spring4
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
Resource Handling in Spring MVC
[Spring Camp 2013] Java Configuration 없인 못살아!
Vagrant와 chef로 개발서버 구축 자동화하기
Ad

kotlinx.serialization

  • 1. kotlinx. serialization Arawn Park SpringRunner 객체를 네트워크를 통해 전송하거나 데이터베이스 또는 파일에 저장할 수 있는 형식으로 변환하는 프로세스
  • 3. ! 자바 생태계의 직렬화 도구를 이용한 JSON 직렬화하기 import com.google.gson.Gson import com.google.gson.reflect.TypeToken class GsonSpec : FunSpec({ val gson = Gson() test("객체를 JSON으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = gson.toJson(data) serialized shouldBe """{"title":"foo","director":"x","rating":0.1}""" val deserialized = gson.fromJson(serialized, Movie::class.java) deserialized shouldBe data } test("리스트를 JSON으로 직렬화 또는 역직렬화하기") { val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9)) val serialized = gson.toJson(data) serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]""" val javaType = object : TypeToken<List<Movie>>() {}.type val deserialized = gson.fromJson<List<Movie>>(serialized, javaType) deserialized shouldBe data } }) Kotlin/JVM
  • 4. ! kotlinx.serialization으로 JSON 직렬화하기 import kotlinx.serialization.json.Json import kotlinx.serialization.encodeToString import kotlinx.serialization.decodeFromString class SimpleKotlinSerializationSpec : FunSpec({ test("객체를 JSON으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = Json.encodeToString(data) serialized shouldBe """{"title":"foo","director":"x","rating":0.1}""" val deserialized = Json.decodeFromString<Movie>(serialized) deserialized shouldBe data } test("리스트를 JSON으로 직렬화 또는 역직렬화하기") { val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9)) val serialized = Json.encodeToString(data) serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]""" val deserialized = Json.decodeFromString<List<Movie>>(serialized) deserialized shouldBe data } }) Kotlin/JVM
  • 5. 2017.07: kotlinx.serialization 프로젝트 시작 2017.09: 0.1 공개 (with Kotlin 1.1) 2020.10: 1.0 발표 (with Kotlin 1.4) 2022.05: 1.3 (with 1.4+) . . .
  • 6. 왜 코틀린은 직렬화 도구를 직접 만들었을까?
  • 7. ! null이 없었는데요 있었습니다 import com.google.gson.Gson import com.google.gson.reflect.TypeToken class GsonSpec : FunSpec({ val gson = Gson() test("역직렬화시 널을 허용하지 않는 속성에 널을 입력해도 예외가 발생하지 않아요") { val serialized = """{"title":"foo","rating":null}""" val javaType = object : TypeToken<Movie>() {}.type val deserialized = gson.fromJson<Movie>(serialized, javaType) deserialized.title shouldBe "foo" deserialized.director shouldBe null deserialized.rating shouldBe 0.0 } }) data class Movie( val title: String, val director: String, val rating: Double = 1.0 ) Kotlin/JVM
  • 8. ! 기본이 안 돼 있네 기본이 import com.google.gson.Gson import com.google.gson.reflect.TypeToken class GsonSpec : FunSpec({ val gson = Gson() test("역직렬화시 기본 인자가 설정된 속성을 지원하지 않아요") { val serialized = """{"title":"foo","director":"x"}""" val deserialized = gson.fromJson(serialized, Movie::class.java) deserialized.rating shouldBe 0.0 } }) data class Movie( val title: String, val director: String, val rating: Double = 1.0 ) Kotlin/JVM
  • 9. ! 거 참 말 많네 import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty class JacksonSpec : FunSpec({ test("데이터 클래스를 JSON으로 직렬화 또는 역직렬화하기") { val mapper = JsonMapper.builder().build() val data = Project("foo", 1.0) val serialized = mapper.writeValueAsString(data) serialized shouldBe """{"name":"foo","version":1.0}""" val deserialized = mapper.readValue(serialized, Project::class.java) deserialized.name shouldBe data.name deserialized.version shouldBe data.version } }) data class Project @JsonCreator constructor( @JsonProperty("name") val name: String, @JsonProperty("version") val version: Double ) Kotlin/JVM
  • 10. ! 거 참 말 많네 second edition import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.module.kotlin.kotlinModule class JacksonSpec : FunSpec({ val mapper = JsonMapper.builder().addModule(kotlinModule()).build() test("객체를 JSON으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = mapper.writeValueAsString(data) serialized shouldBe """{"title":"foo","director":"x","rating":0.1}""" val javaType = object: TypeReference<Movie>() {} val deserialized = mapper.readValue(serialized, javaType) deserialized shouldBe data } test("리스트를 JSON으로 직렬화 또는 역직렬화하기") { val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9)) val serialized = mapper.writeValueAsString(data) serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]""" val javaType = mapper.typeFactory.constructCollectionType(List::class.java, Movie::class.java) val deserialized = mapper.readValue<List<Movie>>(serialized, javaType) deserialized shouldBe data } }) Kotlin/JVM
  • 11. ! 우린 너희만 있으면 돼 Browser Native JVM Android }
  • 13. ! kotlinx.serialization으로 JSON 직렬화하기 import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json class SimpleKotlinSerializationSpec : FunSpec({ test("객체를 JSON으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = Json.encodeToString(Movie.serializer(), data) serialized shouldBe """{"title":"foo","director":"x","rating":0.1}""" val deserialized = Json.decodeFromString(Movie.serializer(), serialized) deserialized shouldBe data } }) @Serializable data class Movie( val title: String, val director: String, val rating: Double = 1.0 ) Kotlin/JVM
  • 14. ! 컴파일 안전 보장 compile-time safe import kotlinx.serialization.Serializable class SimpleKotlinSerializationSpec : FunSpec({ test("컴파일 타임에 직렬화 지원 여부를 확인해요") { data class User(val userName: String) @Serializable data class Project( val name: String, val owner: User, val language: String = "Kotlin" ) } }) Kotlin/JVM
  • 15. ! 명료함 및 간결함 explicit and concise import kotlinx.serialization.json.Json import kotlinx.serialization.encodeToString import kotlinx.serialization.decodeFromString class SimpleKotlinSerializationSpec : FunSpec({ test("객체를 JSON으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = Json.encodeToString(data) serialized shouldBe """{"title":"foo","director":"x","rating":0.1}""" val deserialized = Json.decodeFromString<Movie>(serialized) deserialized shouldBe data } test("리스트를 JSON으로 직렬화 또는 역직렬화하기") { val data = listOf(Movie("foo", "x", 0.1), Movie("bar", "y", 9.9)) val serialized = Json.encodeToString(data) serialized shouldBe """[{"title":"foo","director":"x","rating":0.1},{..}]""" val deserialized = Json.decodeFromString<List<Movie>>(serialized) deserialized shouldBe data } }) Kotlin/JVM
  • 16. ! 코틀린 지향 Kotlin-oriented class SimpleKotlinSerializationSpec : FunSpec({ test("역직렬화시 널을 허용하지 않는 원시타입 속성에 널을 입력되면 예외가 발생해요") { val exception = shouldThrow<SerializationException> { Json.decodeFromString<Movie>("""{"title":"foo","director":"x","rating":null}""") } exception.message shouldBe """ Unexpected JSON token at offset 43: Failed to parse type 'double' for input 'null' JSON input: {"title":"foo","director":"x","rating":null} """.trimIndent() } test("역직렬화시 널을 허용하지 않는 속성에 널이 입력되면 예외가 발생해요") { val exception = shouldThrow<SerializationException> { Json.decodeFromString<Movie>("""{"title":"foo","rating":0.1}""") } exception.message shouldBe """ Field 'director' is required for type with serial name 'Movie', but it was missing """.trimIndent() } test("역직렬화시 기본 인자가 설정된 속성을 지원해요") { val deserialized = Json.decodeFromString<Movie>("""{"title":"foo","director":"x"}""") deserialized.rating shouldBe 1.0 } }) Kotlin/JVM
  • 17. ! 다양한 형식 지원 multi-format import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.encodeToByteArray import kotlinx.serialization.decodeFromByteArray class SimpleKotlinSerializationSpec : FunSpec({ test("객체를 CBOR 형식으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = Cbor.encodeToByteArray(data) serialized.toAsciiHexString() shouldBe """ {BF}etitlecfoohdirectoraxfrating{FB}?{B9}{99}{99}{99}{99}{99}{9A}{FF} """.trimIndent() val deserialized = Cbor.decodeFromByteArray<Movie>(serialized) deserialized shouldBe data } test("객체를 ProtoBuf 형식으로 직렬화 또는 역직렬화하기") { val data = Movie("foo", "x", 0.1) val serialized = ProtoBuf.encodeToByteArray(data) serialized.toAsciiHexString() shouldBe """ {0A}{03}foo{12}{01}x{19}{9A}{99}{99}{99}{99}{99}{B9}? """.trimIndent() val deserialized = ProtoBuf.decodeFromByteArray<Movie>(serialized) deserialized shouldBe data } }) Kotlin/JVM
  • 18. ! 멀티플랫폼 지원 multiplatform JVM Android Browser Native }
  • 20. 멀티플랫폼 지원, 좀 더 가까이서 살펴보기
  • 23. ! 모든 플랫폼에 공유할 로직 작성하기 Com m on Kotlin
  • 24. ! JS 플랫폼에서 사용할 로직 작성하기 Com m on Kotlin Kotlin/JS
  • 25. ! 멀티플랫폼 프로젝트 빌드하기 ❯ ./gradlew clean build Starting Build Settings evaluated using settings file 'kotlinx-serialization/settings.gradle.kts'. Projects loaded. Root project using build file 'kotlinx-serialization/build.gradle.kts'.
 Included projects: [root project 'kotlinx-serialization']
 
 > Task :kotlinNodeJsSetup > Task :kotlinYarnSetup > Task :kotlinNpmInstall > Task :kotlinStoreYarnLock > Task :compileKotlinJs > Task :compileTestKotlinJs > Task :jsTest > Task :build
 
 BUILD SUCCESSFUL in 1m 13s 51 actionable tasks: 45 executed, 6 up-to-date ❯ ls build/libs kotlinx-serialization-js.klib kotlinx-serialization-jvm.jar 
 ❯ ls build/distributions kotlinx-serialization.js kotlinx-serialization.js.map
  • 26. ! Kotlin/JS로 작성된 모듈을 브라우저에서 사용하기 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>kotlinx-serialization</title> </head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script> <script> require(["/assets/js/kotlinx-serialization.js"], function(serialization) { const movies = serialization.Movies const movie = movies.fromJson('{"title":"foo","director":"x","rating":0.1}') console.log(`Movie (title: ${movie.title}, ...)`); }); </script> </body> </html> // file:src/jsMain/kotlin/Movies.kt object Movies { fun fromJson(content: String) = {..} fun fromJsonArray(content: String) = {..} }
  • 27. ! Kotlin/JS로 작성된 모듈을 Node.js에서 사용하기 const serialization = require("./modules/kotlinx-serialization.js") const movies = serialization.Movies const movie = movies.fromJson('{"title":"foo","director":"x","rating":0.1}') console.log(`Movie (title: ${movie.title}, ...)`); // file:src/jsMain/kotlin/Movies.kt object Movies { fun fromJson(content: String) = {..} fun fromJsonArray(content: String) = {..} }
  • 28. ! 하나의 소스로 어디든 실행 할 수 있..어요?
  • 30. 나는 왜 코틀린 직렬화를 사용했나
  • 32. ! 애플리케이션 핵심 코드를 구현 기술로부터 지켜라! 애플리케이션 핵심 코드 }
  • 33. ! 언어가 제공하는 도구는 침투적인 기술일까? 아닐까? 애플리케이션 핵심 코드 }kotlinx. serialization
  • 34. end.