SlideShare a Scribd company logo
1 of 73
Download to read offline
Codableのための
EncoderとDecoderを
自作してみた
クラスメソッド株式会社
Nakayasu Yuichi
About me
中安 佑一
Nakayasu Yuichi
クラスメソッド株式会社
モバイルアプリサービス部 所属
Classmethod, Inc. Mobile Application Service dep
@nkysyuichi
主にiOSアプリエンジニア
iOS App Engineer
Codableって使ってますか?
Codable
Swift4からFoundationに標準搭載された
特定のフォーマットのデータと特定のクラスや構造体との
相互変換を簡単に行えるようにするための
非常に強力なプロトコル
/// A type that can convert itself into and out of an external
representation.
public typealias Codable = Decodable & Encodable
実際は Encodable と Decodable の合成プロトコル
Codable
struct SearchCondition {
let departure: String
let destination: String
let date: Date
let stay: Int
let persons: Int
let keyword: String
}
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
(例) とある旅行検索アプリの検索条件を入れるための構造体
Codable
struct SearchCondition: Codable {
let departure: String
let destination: String
let date: Date
let stay: Int
let persons: Int
let keyword: String
}
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
(例) とある旅行検索アプリの検索条件を入れるための構造体
Codable
let encoder = JSONEncoder()
let encoded = try! encoder.encode(condition)
let json = String(data: encoded, encoding: .utf8)!
SearchCondition > JSON文字列にする
JSONEncoderにSearchConditionを渡してやるだけ
{
"stay" : 3,
"destination" : "Sapporo",
"keyword" : "朝食付き",
"departure" : "Osaka",
"persons" : 1,
"date" : "2018-05-10"
}
Codable
let encoder = JSONEncoder()
let encoded = try! encoder.encode(condition)
let json = String(data: encoded, encoding: .utf8)!
SearchCondition > JSON文字列にする
JSONEncoderにSearchConditionを渡してやるだけ
{
"stay" : 3,
"destination" : "Sapporo",
"keyword" : "朝食付き",
"departure" : "Osaka",
"persons" : 1,
"date" : "2018-05-10"
}
Codable
let encoder = JSONEncoder()
let encoded = try! encoder.encode(condition)
let json = String(data: encoded, encoding: .utf8)!
SearchCondition > JSON文字列にする
JSONEncoderにSearchConditionを渡してやるだけ
{
"stay" : 3,
"destination" : "Sapporo",
"keyword" : "朝食付き",
"departure" : "Osaka",
"persons" : 1,
"date" : "2018-05-10"
}
Codable
let encoder = JSONEncoder()
let encoded = try! encoder.encode(condition)
let json = String(data: encoded, encoding: .utf8)!
SearchCondition > JSON文字列にする
JSONEncoderにSearchConditionを渡してやるだけ
{
"stay" : 3,
"destination" : "Sapporo",
"keyword" : "朝食付き",
"departure" : "Osaka",
"persons" : 1,
"date" : "2018-05-10"
}
Codable
let decoder = JSONDecoder()
let decoded = json.data(using: .utf8)!
let condition = try!
decoder.decode(SearchCondition.self, from: decoded)
JSON文字列 > SearchConditionにする
JSONDecoderにJSON文字列を渡して
SearchConditionの型を指定してやるだけ
Codable
let decoder = JSONDecoder()
let decoded = json.data(using: .utf8)!
let condition = try!
decoder.decode(SearchCondition.self, from: decoded)
JSON文字列 > SearchConditionにする
JSONDecoderにJSON文字列を渡して
SearchConditionの型を指定してやるだけ
Codable
let decoder = JSONDecoder()
let decoded = json.data(using: .utf8)!
let condition = try!
decoder.decode(SearchCondition.self, from: decoded)
JSON文字列 > SearchConditionにする
JSONDecoderにJSON文字列を渡して
SearchConditionの型を指定してやるだけ
Codable
let decoder = JSONDecoder()
let decoded = json.data(using: .utf8)!
let condition = try!
decoder.decode(SearchCondition.self, from: decoded)
JSON文字列 > SearchConditionにする
JSONDecoderにJSON文字列を渡して
SearchConditionの型を指定してやるだけ
Codableって便利ですよね!
Standard Prepared
Swift4で用意されているEncoder / Decoder
- JSONEncoder / JSONDecoder
- PropertyListEncoder / PropertyListDecoder
え? 少なくない?!
だったら、自作してみよう!
作ってみたいもの
URLQueryItemEncoder
Codableなオブジェクトを渡すと、URLQueryItemの配列を返す
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
var components = URLComponents(string: "https://
hogehoge.com")!
components.queryItems =
try! URLQueryItemEncoder().encode(condition)
作ってみたいもの
URLQueryItemEncoder
Codableなオブジェクトを渡すと、URLQueryItemの配列を返す
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
var components = URLComponents(string: "https://
hogehoge.com")!
components.queryItems =
try! URLQueryItemEncoder().encode(condition)
作ってみたいもの
URLQueryItemEncoder
Codableなオブジェクトを渡すと、URLQueryItemの配列を返す
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
var components = URLComponents(string: "https://
hogehoge.com")!
components.queryItems =
try! URLQueryItemEncoder().encode(condition)
作ってみたいもの
URLQueryItemEncoder
Codableなオブジェクトを渡すと、URLQueryItemの配列を返す
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
var components = URLComponents(string: "https://
hogehoge.com")!
components.queryItems =
try! URLQueryItemEncoder().encode(condition)
作ってみたいもの
URLQueryItemDecoder
URLQueryItemの配列を渡すと、Codableなオブジェクトを返す
let urlString = "http://hogehoge.com?
departure=Osaka&destination=Sapporo&date=%5B%2254623157
5.650868%22%5D&stay=3&persons=1&keyword=%E6%9C%9D%E9%A3
%9F%E4%BB%98%E3%81%8D"
let components = URLComponents(string: urlString)
let condition =
try! URLQueryItemDecoder()
.decode(SearchCondition.self,
from: components?.queryItems)
作ってみたいもの
URLQueryItemDecoder
URLQueryItemの配列を渡すと、Codableなオブジェクトを返す
let urlString = "http://hogehoge.com?
departure=Osaka&destination=Sapporo&date=%5B%2254623157
5.650868%22%5D&stay=3&persons=1&keyword=%E6%9C%9D%E9%A3
%9F%E4%BB%98%E3%81%8D"
let components = URLComponents(string: urlString)
let condition =
try! URLQueryItemDecoder()
.decode(SearchCondition.self,
from: components?.queryItems)
作ってみたいもの
URLQueryItemDecoder
URLQueryItemの配列を渡すと、Codableなオブジェクトを返す
let urlString = "http://hogehoge.com?
departure=Osaka&destination=Sapporo&date=%5B%2254623157
5.650868%22%5D&stay=3&persons=1&keyword=%E6%9C%9D%E9%A3
%9F%E4%BB%98%E3%81%8D"
let components = URLComponents(string: urlString)
let condition =
try! URLQueryItemDecoder()
.decode(SearchCondition.self,
from: components?.queryItems)
作ってみたいもの
URLQueryItemDecoder
URLQueryItemの配列を渡すと、Codableなオブジェクトを返す
let urlString = "http://hogehoge.com?
departure=Osaka&destination=Sapporo&date=%5B%2254623157
5.650868%22%5D&stay=3&persons=1&keyword=%E6%9C%9D%E9%A3
%9F%E4%BB%98%E3%81%8D"
let components = URLComponents(string: urlString)
let condition =
try! URLQueryItemDecoder()
.decode(SearchCondition.self,
from: components?.queryItems)
登場人物
登場人物
Encoderプロトコル
protocol Encoder {
var codingPath: [CodingKey] { get }
var userInfo: [CodingUserInfoKey : Any] { get }
func container<Key>(keyedBy type: Key.Type) ->
KeyedEncodingContainer<Key> where Key : CodingKey
func unkeyedContainer() -> UnkeyedEncodingContainer
func singleValueContainer() -> SingleValueEncodingContainer
}
登場人物
3種類のContainer
protocol Encoder {
var codingPath: [CodingKey] { get }
var userInfo: [CodingUserInfoKey : Any] { get }
func container<Key>(keyedBy type: Key.Type) ->
KeyedEncodingContainer<Key> where Key : CodingKey
func unkeyedContainer() -> UnkeyedEncodingContainer
func singleValueContainer() -> SingleValueEncodingContainer
}
- Keyed コンテナ
- Unkeyed コンテナ
- SingleValue コンテナ
実際の変換は彼らが行う
登場人物
3種類のContainer
protocol Encoder {
var codingPath: [CodingKey] { get }
var userInfo: [CodingUserInfoKey : Any] { get }
func container<Key>(keyedBy type: Key.Type) ->
KeyedEncodingContainer<Key> where Key : CodingKey
func unkeyedContainer() -> UnkeyedEncodingContainer
func singleValueContainer() -> SingleValueEncodingContainer
}
- Keyed コンテナ
- Unkeyed コンテナ
- SingleValue コンテナ
<- Struct
<- Protocol
<- Protocol
登場人物
Encoder
(KeyedEncoding
Container)
Keyed
Encoding
Container
Protocol
Unkeyed
Encoding
Container
SingleValue
Encoding
Container
Keyed
コンテナ
クラス
Unkeyed
コンテナ
クラス
SingleValue
コンテナ
クラス
登場人物
Encoder
(KeyedEncoding
Container)
Keyed
Encoding
Container
Protocol
Unkeyed
Encoding
Container
SingleValue
Encoding
Container
Keyed
コンテナ
クラス
Unkeyed
コンテナ
クラス
SingleValue
コンテナ
クラス
構造体 (structure)
プロトコル
登場人物
Decoder
(KeyedDecoding
Container)
Keyed
Decoding
Container
Protocol
Unkeyed
Decoding
Container
SingleValue
Decoding
Container
Keyed
コンテナ
クラス
Unkeyed
コンテナ
クラス
SingleValue
コンテナ
クラス
デコーダも同様
登場人物
CodingKey
struct Student: Codable {
var studentName: String
let grade: Int
let roomNumber: Int
enum Key: String, CodingKey {
case studentName = "student_name"
case grade
case roomNumber = "room_number"
}
}
エンコードとデコードでキーとして使う型
Codableではストアドプロパティの名前をもって
キーが自動的に決定する
カスタマイズもできる
登場人物
CodingKey
struct Student: Codable {
var studentName: String
let grade: Int
let roomNumber: Int
enum Key: String, CodingKey {
case studentName = "student_name"
case grade
case roomNumber = "room_number"
}
}
エンコードとデコードでキーとして使う型
Codableではストアドプロパティの名前をもって
キーが自動的に決定する
カスタマイズもできる
コンテナ
コンテナを実装する
Encoder
Keyed
コンテナ
Unkeyed
コンテナ
SingleValue
コンテナ
Decoder
Keyed
コンテナ
Unkeyed
コンテナ
SingleValue
コンテナ
それぞれ3つのコンテナ x 2 = 6つのコンテナ
コンテナを実装する
共通するインターフェイス
var codingPath: [CodingKey] { get }
mutating func nestedContainer<NestedKey>(keyedBy keyType:
NestedKey.Type, forKey key: Key) ->
KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey
mutating func nestedUnkeyedContainer(forKey key: Key) ->
UnkeyedEncodingContainer
mutating func superEncoder() -> Encoder
コーディングキー系
ネストコンテナ系
コンテナを実装する
ネストコンテナとは?
struct User: Codable {
let name: String
let email: String
}
{
“name” : “Nakayasu”
“attribute” : {
“email” : “nakayasu.yuichi@classmethod.jp”,
“tel” : “06-1234-5678”,
“dept” : “mobile app service”
}
}
相互変換
コンテナを実装する
ネストコンテナとは?
struct User: Codable {
let name: String
let email: String
}
{
“name” : “Nakayasu”
“attribute” : {
“email” : “nakayasu.yuichi@classmethod.jp”,
“tel” : “06-1234-5678”,
“dept” : “mobile app service”
}
}
相互変換
コンテナを実装する
ネストコンテナとは?
struct User: Codable {
let name: String
let email: String
}
{
“name” : “Nakayasu”
“attribute” : {
“email” : “nakayasu.yuichi@classmethod.jp”,
“tel” : “06-1234-5678”,
“dept” : “mobile app service”
}
}
相互変換
コンテナを実装する
struct User: Encodable {
let name: String
let email: String
enum CodingKeys: String, CodingKey {
case name
case attribute
}
enum AttributeCodingKeys: String, CodingKey {
case email
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
var attributeContainer = container.nestedContainer(keyedBy:
AttributeCodingKeys.self, forKey: .attribute)
try attributeContainer.encode(email, forKey: .email)
}
}
話し出すとややこしいので割愛 m(> <)m
コンテナを実装する
共通するインターフェイス
mutating func encodeNil(forKey key: Key) throws
mutating func encode(_ value: Bool, forKey key: Key) throws
mutating func encode(_ value: String, forKey key: Key) throws
mutating func encode(_ value: Double, forKey key: Key) throws
mutating func encode(_ value: Float, forKey key: Key) throws
mutating func encode(_ value: Int, forKey key: Key) throws
mutating func encode(_ value: Int8, forKey key: Key) throws
mutating func encode(_ value: Int16, forKey key: Key) throws
mutating func encode(_ value: Int32, forKey key: Key) throws
mutating func encode(_ value: Int64, forKey key: Key) throws
mutating func encode(_ value: UInt, forKey key: Key) throws
mutating func encode(_ value: UInt8, forKey key: Key) throws
mutating func encode(_ value: UInt16, forKey key: Key) throws
mutating func encode(_ value: UInt32, forKey key: Key) throws
mutating func encode(_ value: UInt64, forKey key: Key) throws
mutating func encode<T>(_ value: T, forKey key: Key) throws where T : Encodable
エンコード処理系
- Nil
- String
- Bool
- Int (5種類)
- UInt (5種類)
- Float
- Double
- Encodable
コンテナを実装する
mutating func encode(_ value: 型, forKey key: Key) throws
共通するインターフェイス
要はプリミティブな型を全部対応しなさいよということ
共通メソッドを呼び出すようにしておけばよい
コンテナを実装する
Keyedコンテナ
キー : 値 になっている形式はこれが呼ばれる
let condition = SearchCondition(
departure : "Osaka",
destination : "Sapporo",
date : Date(),
stay : 3,
persons : 1,
keyword : "朝食付き"
)
Codableな型は
プロパティ名( = キー) とその値でできているので、
おのずとKeyedになっている
コンテナを実装する
Keyedコンテナ
private class URLQueryItemEncoderKeyedContainer<Key>:
KeyedEncodingContainerProtocol where Key: CodingKey {
private var encoder: URLQueryItemEncoder
var codingPath: [CodingKey] {
return encoder.codingPath
}
init(encoder: URLQueryItemEncoder) {
self.encoder = encoder
}
コンテナを実装する
Keyedコンテナ
private class URLQueryItemEncoderKeyedContainer<Key>:
KeyedEncodingContainerProtocol where Key: CodingKey {
private var encoder: URLQueryItemEncoder
var codingPath: [CodingKey] {
return encoder.codingPath
}
init(encoder: URLQueryItemEncoder) {
self.encoder = encoder
}
外側からは存在は知らなくていいので、privateクラス
コンテナを実装する
Keyedコンテナ
private class URLQueryItemEncoderKeyedContainer<Key>:
KeyedEncodingContainerProtocol where Key: CodingKey {
private var encoder: URLQueryItemEncoder
var codingPath: [CodingKey] {
return encoder.codingPath
}
init(encoder: URLQueryItemEncoder) {
self.encoder = encoder
}
エンコーダの参照を持っておく
コンテナを実装する
Keyedコンテナ
private func store(_ value: Any, forKey key: Key) {
let name = key.stringValue
let stringValue = String(describing: value)
let queryItem = URLQueryItem(name: name, value:
stringValue)
encoder.append(queryItem: queryItem)
}
共通メソッド
コンテナを実装する
Keyedコンテナ
private func store(_ value: Any, forKey key: Key) {
let name = key.stringValue
let stringValue = String(describing: value)
let queryItem = URLQueryItem(name: name, value:
stringValue)
encoder.append(queryItem: queryItem)
}
共通メソッド
- CodingKeyからキー名をstringValueで取得できる
- キャメル=>スネークの変換はここでできる
コンテナを実装する
Keyedコンテナ
private func store(_ value: Any, forKey key: Key) {
let name = key.stringValue
let stringValue = String(describing: value)
let queryItem = URLQueryItem(name: name, value:
stringValue)
encoder.append(queryItem: queryItem)
}
共通メソッド
- URLパラメータは文字列なので、どの型も文字列で扱う
- プリミティブ以外は色々対策が必要
コンテナを実装する
Keyedコンテナ
private func store(_ value: Any, forKey key: Key) {
let name = key.stringValue
let stringValue = String(describing: value)
let queryItem = URLQueryItem(name: name, value:
stringValue)
encoder.append(queryItem: queryItem)
}
共通メソッド
- URLQueryItemを作ってエンコーダに流し込み
- appendは後でエンコーダに実装する
コンテナを実装する
Keyedコンテナ
func encodeNil(forKey key: Key) throws { /* NOP */ }
func encode(_ value: Bool, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: String, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Double, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Float, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int8, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int16, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int32, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int64, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt8, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt16, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt32, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt64, forKey key: Key) throws { store(value, forKey: key) }
共通メソッド
func encodeNil(forKey key: Key) throws { /* NOP */ }
func encode(_ value: Bool, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: String, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Double, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Float, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int8, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int16, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int32, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: Int64, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt8, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt16, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt32, forKey key: Key) throws { store(value, forKey: key) }
func encode(_ value: UInt64, forKey key: Key) throws { store(value, forKey: key) }
コンテナを実装する
Keyedコンテナ
{ store(value, forKey: key) }
共通メソッド
エンコーダ
エンコーダを実装する
class URLQueryItemEncoder: Encoder {
var codingPath = [CodingKey]()
var userInfo = [CodingUserInfoKey : Any]()
private var queryItems: [URLQueryItem]?
fileprivate func append(queryItem: URLQueryItem) {
if queryItems == nil {
queryItems = []
}
queryItems!.append(queryItem)
}
エンコーダを実装する
class URLQueryItemEncoder: Encoder {
var codingPath = [CodingKey]()
var userInfo = [CodingUserInfoKey : Any]()
private var queryItems: [URLQueryItem]?
fileprivate func append(queryItem: URLQueryItem) {
if queryItems == nil {
queryItems = []
}
queryItems!.append(queryItem)
}
エンコーダを実装する
class URLQueryItemEncoder: Encoder {
var codingPath = [CodingKey]()
var userInfo = [CodingUserInfoKey : Any]()
private var queryItems: [URLQueryItem]?
fileprivate func append(queryItem: URLQueryItem) {
if queryItems == nil {
queryItems = []
}
queryItems!.append(queryItem)
}
コンテナから呼び出すためのfileprivateなメソッド
エンコーダを実装する
func container<Key>(keyedBy type: Key.Type)
-> KeyedEncodingContainer<Key> where Key : CodingKey {
let container =
URLQueryItemKeyedEncodingContainer<Key>(encoder: self)
return KeyedEncodingContainer(container)
}
Keyedコンテナを返す
func unkeyedContainer() -> UnkeyedEncodingContainer {
}
func singleValueContainer() -> SingleValueEncodingContainer {
}
↑ すいません割愛します m(> <)m
エンコーダを実装する
func container<Key>(keyedBy type: Key.Type)
-> KeyedEncodingContainer<Key> where Key : CodingKey {
let container =
URLQueryItemKeyedEncodingContainer<Key>(encoder: self)
return KeyedEncodingContainer(container)
}
Keyedコンテナを返す
エンコーダを実装する
func container<Key>(keyedBy type: Key.Type)
-> KeyedEncodingContainer<Key> where Key : CodingKey {
let container =
URLQueryItemKeyedEncodingContainer<Key>(encoder: self)
return KeyedEncodingContainer(container)
}
Keyedコンテナを返す
エンコーダを実装する
private var queryItems: [URLQueryItem]?
func encode<T>(_ value: T) throws
-> [URLQueryItem]? where T : Encodable {
try value.encode(to: self)
return queryItems
}
encodeメソッドは自前で作る
エンコーダを実装する
private var queryItems: [URLQueryItem]?
func encode<T>(_ value: T) throws
-> [URLQueryItem]? where T : Encodable {
try value.encode(to: self)
return queryItems
}
encodeメソッドは自前で作る
エンコーダを実装する
private var queryItems: [URLQueryItem]?
func encode<T>(_ value: T) throws
-> [URLQueryItem]? where T : Encodable {
try value.encode(to: self)
return queryItems
}
encodeメソッドは自前で作る
public protocol Encodable {
public func encode(to encoder: Encoder) throws
}
実際に使うと
作ってみたいもの
URLQueryItemEncoder
Codableなオブジェクトを渡すと、URLQueryItemの配列を返す
let condition = SearchCondition(
departure: "Osaka",
destination: "Sapporo",
date: Date(),
stay: 3,
persons: 1,
keyword: "朝食付き"
)
var components = URLComponents(string: "https://
hogehoge.com")!
components.queryItems =
try! URLQueryItemEncoder().encode(condition)
コンテナを実装する
https://hogehoge.com?
departure=Osaka&destination=Sapporo&date=20
18-05-08%2009:25:04%20+0000&stay=3&persons=
1&keyword=%E6%9C%9D%E9%A3%9F%E4%BB%98%E3%81
%8D
コンテナを実装する
https://hogehoge.com?
departure=Osaka&destination=Sapporo&date=20
18-05-08%2009:25:04%20+0000&stay=3&persons=
1&keyword=%E6%9C%9D%E9%A3%9F%E4%BB%98%E3%81
%8D
最後に
ほんとに汎用性を持たせようとすると、
Unkeyedコンテナ、SingleValueコンテナを
意識した設計にしなければならない
作ってみて
デコーダの作成はエンコーダの逆ではあるが
頭が整理できてないとややこしい
ネストコンテナも意識した設計にしなければ
ならない
作ってみて
Appleさん作ってよ
でも楽しいよ
作ってみて
ありがとうございました

More Related Content

Similar to CodableのためのEncoderとDecoderを 自作してみた

本当にあった怖い話し (やきに駆動 2.0)
本当にあった怖い話し (やきに駆動 2.0)本当にあった怖い話し (やきに駆動 2.0)
本当にあった怖い話し (やきに駆動 2.0)Oda Shinsuke
 
Scala + Finagleの魅力
Scala + Finagleの魅力Scala + Finagleの魅力
Scala + Finagleの魅力Kota Mizushima
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...Yoshifumi Kawai
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platformToru Yamaguchi
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化Takuya Ueda
 
Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版Takuya Matsunaga
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語るAkira Takahashi
 
函数プログラミングの エッセンスと考え方
函数プログラミングのエッセンスと考え方函数プログラミングのエッセンスと考え方
函数プログラミングの エッセンスと考え方啓 小笠原
 
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門Preferred Networks
 
Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Tomoaki Shimizu
 
“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...Masahiro Sakai
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~Fujio Kojima
 
社内向けTech Talk資料~Fluentdの基本紹介~
社内向けTech Talk資料~Fluentdの基本紹介~ 社内向けTech Talk資料~Fluentdの基本紹介~
社内向けTech Talk資料~Fluentdの基本紹介~ Daisuke Ikeda
 
Elasticsearchの基本動作まとめ
Elasticsearchの基本動作まとめElasticsearchの基本動作まとめ
Elasticsearchの基本動作まとめ朋哉 池田
 
Lombokのススメ
LombokのススメLombokのススメ
Lombokのススメなべ
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.specKent Ohashi
 
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansaiWWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansaiTomohiro Kumagai
 

Similar to CodableのためのEncoderとDecoderを 自作してみた (20)

本当にあった怖い話し (やきに駆動 2.0)
本当にあった怖い話し (やきに駆動 2.0)本当にあった怖い話し (やきに駆動 2.0)
本当にあった怖い話し (やきに駆動 2.0)
 
Scala + Finagleの魅力
Scala + Finagleの魅力Scala + Finagleの魅力
Scala + Finagleの魅力
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化
 
Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語る
 
函数プログラミングの エッセンスと考え方
函数プログラミングのエッセンスと考え方函数プログラミングのエッセンスと考え方
函数プログラミングの エッセンスと考え方
 
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
 
実践 NestJS
実践 NestJS実践 NestJS
実践 NestJS
 
Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!
 
“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...“Design and Implementation of Generics for the .NET Common Language Runtime”他...
“Design and Implementation of Generics for the .NET Common Language Runtime”他...
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
 
社内向けTech Talk資料~Fluentdの基本紹介~
社内向けTech Talk資料~Fluentdの基本紹介~ 社内向けTech Talk資料~Fluentdの基本紹介~
社内向けTech Talk資料~Fluentdの基本紹介~
 
Elasticsearchの基本動作まとめ
Elasticsearchの基本動作まとめElasticsearchの基本動作まとめ
Elasticsearchの基本動作まとめ
 
Lombokのススメ
LombokのススメLombokのススメ
Lombokのススメ
 
ScalaMatsuri 2016
ScalaMatsuri 2016ScalaMatsuri 2016
ScalaMatsuri 2016
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.spec
 
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansaiWWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
 

CodableのためのEncoderとDecoderを 自作してみた