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

Swift India Conf 2019: Journey Of Codable

Swift India Conf 2019: Journey Of Codable

Speaker: Bharath Nagaraj Rao, Senior iOS Engineer, Walmart Labs


LinkedIn: https://www.linkedin.com/in/bharath-nagaraj-rao-0b180527/

Bio: A seasoned iOS engineer, fan of Apple’s technologies & products. Presented tech talks related to iOS/Obj C/Swift in various meetups and events. A trekking enthusiast loves to watch classic movies. In pursuit of understanding rules of Sanskrit grammar and apply that in technology to solve problems.

Abstract: With Codable which got introduced in Swift 4, JSON parsing has become a lot easier than it’s ever been before. In this talk, we will trace the journey of Codable, the motivation behind its proposal & understand it's implementation in the Swift standard library. We will also explore how Codable can make a developer's life easier through examples ranging from basic to complex ones to understand the flexibility it offers to customize for our use cases.

Eeb061c8b2816b771920da1b3e7904a3?s=128

Swift India

July 28, 2019
Tweet

Transcript

  1. Bharath Nagaraj Rao Journey of Codable

  2. 1 TB If you want to understand today, you have

    to search yesterday - Pearl S Buck Nobel Laureate 1.2 MB
  3. Serialization Native Domain Objects JSON/XML Marshalling Encoding Serialization Decoding Unmarshalling

    Deserialization
  4. class Movie { /// Name of the movie let name:

    String /// Director let director: String /// Duration in minutess let duration: Int } Encode <…aea6ffa…> Serialization
  5. class Movie { /// Name of the movie let name:

    String /// Director let director: String /// Duration in minutess let duration: Int } Decode <…aea6ffa…> Serialization
  6. NSCoding Lightweight Obj C protocol #available(iOS 2, *) Supports only

    NSObject types No support for Swift structs, enums No default error handling
  7. First class serialization Type safety Ease of usage Customizable &

    flexible No/Minimum boilerplate code
  8. Codable

  9. Codable extension Movie: Equatable { static func == (lhs: Movie,

    rhs: Movie) -> Bool { return lhs.name == rhs.name && lhs.director == rhs.director && lhs.duration == rhs.duration } } Default implementation by compiler Automatic synthesis of Equatable swift >= 4.1
  10. Codable Default implementation by compiler Automatic synthesis of Equatable swift

    >= 4.1 Automatic synthesis of Hashable extension Movie: Hashable { var hashValue: Int { return name.hashValue ^ director.hashValue ^ duration.hashValue } }
  11. Codable Default implementation by compiler Automatic synthesis of Equatable swift

    >= 4.1 Automatic synthesis of Hashable Automatic codable conformance
  12. Codable types Standard library types Int String Bool Double Float

    Int 8 Int 16 Int 32 Int 64 UInt UInt 8 UInt 16 UInt 32 UInt 64
  13. Codable types %{ codable_types = ['Bool', 'String', 'Double', 'Float', 'Int',

    'Int8', 'Int16', 'Int32', 'Int64', 'UInt', 'UInt8', 'UInt16', 'UInt32', 'UInt64'] }% Standard library types swift/stdlib/public/core/Codable.swift.gyb % for type in codable_types: /// Encodes the given value for the given key. /// /// - parameter value: The value to encode. /// - parameter key: The key to associate the value with. /// - throws: `EncodingError.invalidValue` if the given value is invalid in /// the current context for this format. public mutating func encode(_ value: ${type}, forKey key: Key) throws { try _box.encode(value, forKey: key) } % end
  14. Codable types Standard library types Int UInt Float Double Bool

    String Date Data URL Arrays of Codable types Dictionary of Codable types
  15. None
  16. Codable public typealias Codable = Encodable & Decodable public protocol

    Decodable { /// Creates a new instance by decoding from the given decoder. /// /// This initializer throws an error if reading from the decoder fails, or /// if the data read is corrupted or otherwise invalid. /// /// - Parameter decoder: The decoder to read data from. init(from decoder: Decoder) throws } public protocol Encodable { /// Encodes this value into the given encoder. /// /// If the value fails to encode anything, `encoder` will encode an empty /// keyed container in its place. /// /// This function throws an error if any values are invalid for the given /// encoder's format. /// /// - Parameter encoder: The encoder to write data to. func encode(to encoder: Encoder) throws }
  17. KeyedDecodingContainer KeyedEncodingContainer Key : Value UnkeyedDecodingContainer UnkeyedEncodingContainer [ CodableType, CodableType,

    CodableType] SingleValueEncodingContainer SingleValueDecodingContainer 123 func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> func unkeyedContainer() throws -> UnkeyedDecodingContainer func singleValueContainer() throws -> SingleValueDecodingContainer Encoder Decoder
  18. import Foundation let jsonString = """ { "name" : "Roma",

    "country" : "Mexico", "director" : "Alfonso Cuarón", "released" : true, "duration" : 135 } “"" guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Check your input & revisit again!") }
  19. struct Movie: Decodable { /// Name of the movie let

    name: String /// Country of origin let country: String /// Director of the movie let director: String /// Release status let released: Bool /// Duration in minutes let duration: Int } do { // That's all folks! let movie = try JSONDecoder().decode(Movie.self, from: jsonData) } catch { print("Exception - \(error.localizedDescription)") }
  20. import Foundation let jsonString = """ { "name" : "Roma",

    "country" : "Mexico", "director" : "Alfonso Cuarón", "released" : true, "duration" : 135 } “"" guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Check your input & revisit again!") }
  21. import Foundation let jsonString = """ { "name" : "Roma",

    "country_name" : "Mexico", "director_name" : "Alfonso Cuarón", “released_status" : true, "duration" : 135 } “"" guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Check your input & revisit again!") }
  22. struct Movie: Decodable { /// Name of the movie let

    name: String /// Country of origin let countryName: String /// Director of the movie let directorName: String /// Release status let releasedStatus: Bool /// Duration in minutes let duration: Int } let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase do { let movie = try decoder.decode(Movie.self, from: jsonData) } catch { print("Exception - \(error.localizedDescription)") }
  23. Demo

  24. Custom Coders import XMLParsing let jsonString = """ <movie> <name>Roma</name>

    <country>Mexico</country> <director>Alfonso Cuarón</director> <released>true</released> <duration>135</duration> </movie> """ guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Check your input data & come back again!") } struct Movie: Codable { let name: String let country: String let director: String let released: Bool let duration: Int } do { let movie = try XMLDecoder().decode(Movie.self, from: jsonData) } catch { print("Exception - \(error.localizedDescription)") } Source : https://github.com/ShawnMoore/XMLParsing
  25. public protocol TopLevelDecoder { associatedtype Input func decode<T>(_ type: T.Type,

    from: Self.Input) throws -> T where T : Decodable } extension JSONDecoder: TopLevelDecoder {} Combine
  26. public protocol TopLevelDecoder { associatedtype Input func decode<T>(_ type: T.Type,

    from: Self.Input) throws -> T where T : Decodable } extension JSONDecoder: TopLevelDecoder {} Combine _ = URLSession.shared.dataTaskPublisher(for: request) .tryMap { return $0.data } .decode(type: Movie.self, decoder: JSONDecoder()) .sink(receiveCompletion: { _ in print("Received completion") }, receiveValue: { movie in self.winnerLabel.text = " Best director is \(movie.director)" }) let request = URLRequest(url: URL(string: "https://oscarwinners.org/<directors>")!) import Combine
  27. Source : https://itnext.io/swift-json-performance-ce9438632b02 Performance

  28. Codable

  29. References https://developer.apple.com/videos/play/wwdc2017/212/ https://github.com/apple/swift-evolution/blob/master/proposals/0166- swift-archival-serialization.md https://github.com/apple/swift-evolution/blob/master/proposals/0167- swift-encoders.md https://github.com/apple/swift-evolution/blob/master/proposals/0239- codable-range.md https://forums.swift.org/t/codable-improvements-and-refinements/19426

  30. साधूनां दशर्नं पुण्यं तीथर्भूता िह साधवः I तीथर्ं फलते कालेन

    सद्यः साधुसमागमः II चाणक्यनीित : १२-०८ sādhūnāṃ darśanaṃ puṇyaṃ tīrthabhūtā hi sādhavaḥ I tīrthaṃ phalate kālena sadyaḥ sādhusamāgamaḥ II cāṇakyanīti : 12-08
  31. साधूनां दशर्नं पुण्यं तीथर्भूता िह साधवः I तीथर्ं फलते कालेन

    सद्यः साधुसमागमः II चाणक्यनीित : १२-०८ Meeting scholars is as meritorious as visiting holy places. Fruits of visiting a place is obtained over a period of time but the very sight of scholars/experts brings merit at once.
  32. Thank You! https://github.com/bharathnagarajrao