Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Codable用のEncoder/Decoderを作ってみた

 Codable用のEncoder/Decoderを作ってみた

Codableは非常に強力な機能のひとつです。しかしながらそれを生かすEncoderやDecoderはswift4時点ではあまり標準で用意されていません。ならば自作してみようというテーマです。

Avatar for Yuichi Nakayasu

Yuichi Nakayasu

May 10, 2018
Tweet

More Decks by Yuichi Nakayasu

Other Decks in Programming

Transcript

  1. $PEBCMF 4XJGU͔Β'PVOEBUJPOʹඪ४౥ࡌ͞Εͨ ಛఆͷϑΥʔϚοτͷσʔλͱಛఆͷΫϥε΍ߏ଄ମͱͷ ૬ޓม׵Λ؆୯ʹߦ͑ΔΑ͏ʹ͢ΔͨΊͷ ඇৗʹڧྗͳϓϩτίϧ /// A type that can

    convert itself into and out of an external representation. public typealias Codable = Decodable & Encodable ࣮ࡍ͸&ODPEBCMFͱ%FDPEBCMFͷ߹੒ϓϩτίϧ
  2. $PEBCMF 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: "ே৯෇͖" ) ྫ ͱ͋ΔཱྀߦݕࡧΞϓϦͷݕࡧ৚݅ΛೖΕΔͨΊͷߏ଄ମ
  3. $PEBCMF 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: "ே৯෇͖" ) ྫ ͱ͋ΔཱྀߦݕࡧΞϓϦͷݕࡧ৚݅ΛೖΕΔͨΊͷߏ଄ମ
  4. $PEBCMF let encoder = JSONEncoder() let encoded = try! encoder.encode(condition)

    let json = String(data: encoded, encoding: .utf8)! 4FBSDI$POEJUJPO+40/จࣈྻʹ͢Δ +40/&ODPEFSʹ4FBSDI$POEJUJPOΛ౉ͯ͠΍Δ͚ͩ { "stay" : 3, "destination" : "Sapporo", "keyword" : "ே৯෇͖", "departure" : "Osaka", "persons" : 1, "date" : "2018-05-10" }
  5. $PEBCMF let encoder = JSONEncoder() let encoded = try! encoder.encode(condition)

    let json = String(data: encoded, encoding: .utf8)! 4FBSDI$POEJUJPO+40/จࣈྻʹ͢Δ +40/&ODPEFSʹ4FBSDI$POEJUJPOΛ౉ͯ͠΍Δ͚ͩ { "stay" : 3, "destination" : "Sapporo", "keyword" : "ே৯෇͖", "departure" : "Osaka", "persons" : 1, "date" : "2018-05-10" }
  6. $PEBCMF let encoder = JSONEncoder() let encoded = try! encoder.encode(condition)

    let json = String(data: encoded, encoding: .utf8)! 4FBSDI$POEJUJPO+40/จࣈྻʹ͢Δ +40/&ODPEFSʹ4FBSDI$POEJUJPOΛ౉ͯ͠΍Δ͚ͩ { "stay" : 3, "destination" : "Sapporo", "keyword" : "ே৯෇͖", "departure" : "Osaka", "persons" : 1, "date" : "2018-05-10" }
  7. $PEBCMF let encoder = JSONEncoder() let encoded = try! encoder.encode(condition)

    let json = String(data: encoded, encoding: .utf8)! 4FBSDI$POEJUJPO+40/จࣈྻʹ͢Δ +40/&ODPEFSʹ4FBSDI$POEJUJPOΛ౉ͯ͠΍Δ͚ͩ { "stay" : 3, "destination" : "Sapporo", "keyword" : "ே৯෇͖", "departure" : "Osaka", "persons" : 1, "date" : "2018-05-10" }
  8. $PEBCMF let decoder = JSONDecoder() let decoded = json.data(using: .utf8)!

    let condition = try! decoder.decode(SearchCondition.self, from: decoded) +40/จࣈྻ4FBSDI$POEJUJPOʹ͢Δ +40/%FDPEFSʹ+40/จࣈྻΛ౉ͯ͠ 4FBSDI$POEJUJPOͷܕΛࢦఆͯ͠΍Δ͚ͩ
  9. $PEBCMF let decoder = JSONDecoder() let decoded = json.data(using: .utf8)!

    let condition = try! decoder.decode(SearchCondition.self, from: decoded) +40/จࣈྻ4FBSDI$POEJUJPOʹ͢Δ +40/%FDPEFSʹ+40/จࣈྻΛ౉ͯ͠ 4FBSDI$POEJUJPOͷܕΛࢦఆͯ͠΍Δ͚ͩ
  10. $PEBCMF let decoder = JSONDecoder() let decoded = json.data(using: .utf8)!

    let condition = try! decoder.decode(SearchCondition.self, from: decoded) +40/จࣈྻ4FBSDI$POEJUJPOʹ͢Δ +40/%FDPEFSʹ+40/จࣈྻΛ౉ͯ͠ 4FBSDI$POEJUJPOͷܕΛࢦఆͯ͠΍Δ͚ͩ
  11. $PEBCMF let decoder = JSONDecoder() let decoded = json.data(using: .utf8)!

    let condition = try! decoder.decode(SearchCondition.self, from: decoded) +40/จࣈྻ4FBSDI$POEJUJPOʹ͢Δ +40/%FDPEFSʹ+40/จࣈྻΛ౉ͯ͠ 4FBSDI$POEJUJPOͷܕΛࢦఆͯ͠΍Δ͚ͩ
  12. ࡞ͬͯΈ͍ͨ΋ͷ 63-2VFSZ*UFN&ODPEFS $PEBCMFͳΦϒδΣΫτΛ౉͢ͱɺ63-2VFSZ*UFNͷ഑ྻΛฦ͢ 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)
  13. ࡞ͬͯΈ͍ͨ΋ͷ 63-2VFSZ*UFN&ODPEFS $PEBCMFͳΦϒδΣΫτΛ౉͢ͱɺ63-2VFSZ*UFNͷ഑ྻΛฦ͢ 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)
  14. ࡞ͬͯΈ͍ͨ΋ͷ 63-2VFSZ*UFN&ODPEFS $PEBCMFͳΦϒδΣΫτΛ౉͢ͱɺ63-2VFSZ*UFNͷ഑ྻΛฦ͢ 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)
  15. ࡞ͬͯΈ͍ͨ΋ͷ 63-2VFSZ*UFN&ODPEFS $PEBCMFͳΦϒδΣΫτΛ౉͢ͱɺ63-2VFSZ*UFNͷ഑ྻΛฦ͢ 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)
  16. ొ৔ਓ෺ &ODPEFSϓϩτίϧ 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 }
  17. ొ৔ਓ෺ छྨͷ$POUBJOFS 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 } ,FZFEίϯςφ 6OLFZFEίϯςφ 4JOHMF7BMVFίϯςφ ࣮ࡍͷม׵͸൴Β͕ߦ͏
  18. ొ৔ਓ෺ छྨͷ$POUBJOFS 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 } ,FZFEίϯςφ 6OLFZFEίϯςφ 4JOHMF7BMVFίϯςφ 4USVDU 1SPUPDPM 1SPUPDPM
  19. ొ৔ਓ෺ &ODPEFS ,FZFE&ODPEJOH $POUBJOFS ,FZFE &ODPEJOH $POUBJOFS 1SPUPDPM 6OLFZFE &ODPEJOH

    $POUBJOFS 4JOHMF7BMVF &ODPEJOH $POUBJOFS ,FZFE ίϯςφ Ϋϥε 6OLFZFE ίϯςφ Ϋϥε 4JOHMF7BMVF ίϯςφ Ϋϥε
  20. ొ৔ਓ෺ &ODPEFS ,FZFE&ODPEJOH $POUBJOFS ,FZFE &ODPEJOH $POUBJOFS 1SPUPDPM 6OLFZFE &ODPEJOH

    $POUBJOFS 4JOHMF7BMVF &ODPEJOH $POUBJOFS ,FZFE ίϯςφ Ϋϥε 6OLFZFE ίϯςφ Ϋϥε 4JOHMF7BMVF ίϯςφ Ϋϥε ߏ଄ମ TUSVDUVSF ϓϩτίϧ
  21. ొ৔ਓ෺ %FDPEFS ,FZFE%FDPEJOH $POUBJOFS ,FZFE %FDPEJOH $POUBJOFS 1SPUPDPM 6OLFZFE %FDPEJOH

    $POUBJOFS 4JOHMF7BMVF %FDPEJOH $POUBJOFS ,FZFE ίϯςφ Ϋϥε 6OLFZFE ίϯςφ Ϋϥε 4JOHMF7BMVF ίϯςφ Ϋϥε σίʔμ΋ಉ༷
  22. ొ৔ਓ෺ $PEJOH,FZ 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" } } ΤϯίʔυͱσίʔυͰΩʔͱͯ͠࢖͏ܕ $PEBCMFͰ͸ετΞυϓϩύςΟͷ໊લΛ΋ͬͯ Ωʔ͕ࣗಈతʹܾఆ͢Δ ΧελϚΠζ΋Ͱ͖Δ
  23. ొ৔ਓ෺ $PEJOH,FZ 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" } } ΤϯίʔυͱσίʔυͰΩʔͱͯ͠࢖͏ܕ $PEBCMFͰ͸ετΞυϓϩύςΟͷ໊લΛ΋ͬͯ Ωʔ͕ࣗಈతʹܾఆ͢Δ ΧελϚΠζ΋Ͱ͖Δ
  24. ίϯςφΛ࣮૷͢Δ &ODPEFS ,FZFE ίϯςφ 6OLFZFE ίϯςφ 4JOHMF7BMVF ίϯςφ %FDPEFS ,FZFE

    ίϯςφ 6OLFZFE ίϯςφ 4JOHMF7BMVF ίϯςφ ͦΕͧΕͭͷίϯςφYͭͷίϯςφ
  25. ίϯςφΛ࣮૷͢Δ ڞ௨͢ΔΠϯλʔϑΣΠε 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 ίʔσΟϯάΩʔܥ ωετίϯςφܥ
  26. ίϯςφΛ࣮૷͢Δ ωετίϯςφͱ͸ struct User: Codable { let name: String let

    email: String } { “name” : “Nakayasu” “attribute” : { “email” : “[email protected]”, “tel” : “06-1234-5678”, “dept” : “mobile app service” } } ૬ޓม׵
  27. ίϯςφΛ࣮૷͢Δ ωετίϯςφͱ͸ struct User: Codable { let name: String let

    email: String } { “name” : “Nakayasu” “attribute” : { “email” : “[email protected]”, “tel” : “06-1234-5678”, “dept” : “mobile app service” } } ૬ޓม׵
  28. ίϯςφΛ࣮૷͢Δ ωετίϯςφͱ͸ struct User: Codable { let name: String let

    email: String } { “name” : “Nakayasu” “attribute” : { “email” : “[email protected]”, “tel” : “06-1234-5678”, “dept” : “mobile app service” } } ૬ޓม׵
  29. ίϯςφΛ࣮૷͢Δ 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) } } ࿩͠ग़͢ͱ΍΍͍͜͠ͷͰׂѪN  N
  30. ίϯςφΛ࣮૷͢Δ ڞ௨͢ΔΠϯλʔϑΣΠε 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 Τϯίʔυॲཧܥ
  31.  /JM  4USJOH  #PPM  *OU छྨ 

     6*OU छྨ   'MPBU  %PVCMF  &ODPEBCMF ίϯςφΛ࣮૷͢Δ mutating func encode(_ value: ܕ, forKey key: Key) throws ڞ௨͢ΔΠϯλʔϑΣΠε ཁ͸ϓϦϛςΟϒͳܕΛશ෦ରԠ͠ͳ͍͞Αͱ͍͏͜ͱ ڞ௨ϝιουΛݺͼग़͢Α͏ʹ͓͚ͯ͠͹Α͍
  32. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ lΩʔ஋lʹͳ͍ͬͯΔܗࣜ͸͜Ε͕ݺ͹ΕΔ let condition = SearchCondition( departure : "Osaka",

    destination : "Sapporo", date : Date(), stay : 3, persons : 1, keyword : "ே৯෇͖" ) $PEBCMFͳܕ͸ ϓϩύςΟ໊ Ωʔ ͱͦͷ஋ͰͰ͖͍ͯΔͷͰɺ ͓ͷͣͱ,FZFEʹͳ͍ͬͯΔ
  33. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ private class URLQueryItemEncoderKeyedContainer<Key>: KeyedEncodingContainerProtocol where Key: CodingKey {

    private var encoder: URLQueryItemEncoder var codingPath: [CodingKey] { return encoder.codingPath } init(encoder: URLQueryItemEncoder) { self.encoder = encoder }
  34. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ private class URLQueryItemEncoderKeyedContainer<Key>: KeyedEncodingContainerProtocol where Key: CodingKey {

    private var encoder: URLQueryItemEncoder var codingPath: [CodingKey] { return encoder.codingPath } init(encoder: URLQueryItemEncoder) { self.encoder = encoder } ֎ଆ͔Β͸ଘࡏ͸஌Βͳ͍͍ͯ͘ͷͰɺQSJWBUFΫϥε
  35. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ private class URLQueryItemEncoderKeyedContainer<Key>: KeyedEncodingContainerProtocol where Key: CodingKey {

    private var encoder: URLQueryItemEncoder var codingPath: [CodingKey] { return encoder.codingPath } init(encoder: URLQueryItemEncoder) { self.encoder = encoder } ΤϯίʔμͷࢀরΛ͓࣋ͬͯ͘
  36. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ 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) } ڞ௨ϝιου
  37. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ 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) } ڞ௨ϝιου $PEJOH,FZ͔ΒΩʔ໊ΛTUSJOH7BMVFͰऔಘͰ͖Δ ΩϟϝϧεωʔΫͷม׵͸͜͜ͰͰ͖Δ
  38. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ 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) } ڞ௨ϝιου 63-ύϥϝʔλ͸จࣈྻͳͷͰɺͲͷܕ΋จࣈྻͰѻ͏ ϓϦϛςΟϒҎ֎͸৭ʑରࡦ͕ඞཁ
  39. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ 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) } ڞ௨ϝιου 63-2VFSZ*UFNΛ࡞ͬͯΤϯίʔμʹྲྀ͠ࠐΈ BQQFOE͸ޙͰΤϯίʔμʹ࣮૷͢Δ
  40. ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ 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) } ڞ௨ϝιου
  41. 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) } ίϯςφΛ࣮૷͢Δ ,FZFEίϯςφ { store(value, forKey: key) } ڞ௨ϝιου
  42. ΤϯίʔμΛ࣮૷͢Δ 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) }
  43. ΤϯίʔμΛ࣮૷͢Δ 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) }
  44. ΤϯίʔμΛ࣮૷͢Δ 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) } ίϯςφ͔Βݺͼग़ͨ͢ΊͷpMFQSJWBUFͳϝιου
  45. ΤϯίʔμΛ࣮૷͢Δ func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key :

    CodingKey { let container = URLQueryItemKeyedEncodingContainer<Key>(encoder: self) return KeyedEncodingContainer(container) } ,FZFEίϯςφΛฦ͢ func unkeyedContainer() -> UnkeyedEncodingContainer { } func singleValueContainer() -> SingleValueEncodingContainer { } ˢ͍͢·ͤΜׂѪ͠·͢N  N
  46. ΤϯίʔμΛ࣮૷͢Δ func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key :

    CodingKey { let container = URLQueryItemKeyedEncodingContainer<Key>(encoder: self) return KeyedEncodingContainer(container) } ,FZFEίϯςφΛฦ͢
  47. ΤϯίʔμΛ࣮૷͢Δ func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key :

    CodingKey { let container = URLQueryItemKeyedEncodingContainer<Key>(encoder: self) return KeyedEncodingContainer(container) } ,FZFEίϯςφΛฦ͢
  48. ΤϯίʔμΛ࣮૷͢Δ private var queryItems: [URLQueryItem]? func encode<T>(_ value: T) throws

    -> [URLQueryItem]? where T : Encodable { try value.encode(to: self) return queryItems } FODPEFϝιου͸ࣗલͰ࡞Δ
  49. ΤϯίʔμΛ࣮૷͢Δ private var queryItems: [URLQueryItem]? func encode<T>(_ value: T) throws

    -> [URLQueryItem]? where T : Encodable { try value.encode(to: self) return queryItems } FODPEFϝιου͸ࣗલͰ࡞Δ
  50. ΤϯίʔμΛ࣮૷͢Δ private var queryItems: [URLQueryItem]? func encode<T>(_ value: T) throws

    -> [URLQueryItem]? where T : Encodable { try value.encode(to: self) return queryItems } FODPEFϝιου͸ࣗલͰ࡞Δ public protocol Encodable { public func encode(to encoder: Encoder) throws }
  51. ࡞ͬͯΈ͍ͨ΋ͷ 63-2VFSZ*UFN&ODPEFS $PEBCMFͳΦϒδΣΫτΛ౉͢ͱɺ63-2VFSZ*UFNͷ഑ྻΛฦ͢ 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)