iOSConfSG 2017: Decoding Codable

Ddd6d3bac7772fa67fc5e312a18bdaec?s=47 sammyd
October 19, 2017

iOSConfSG 2017: Decoding Codable

A discussion on using Codable in Swift 4 for serialisation.

Code available at https://github.com/sammyd/iOSConfSG2017_Codable

Ddd6d3bac7772fa67fc5e312a18bdaec?s=128

sammyd

October 19, 2017
Tweet

Transcript

  1. Decoding Codable

  2. None
  3. @iwantmyrealname github.com/sammyd

  4. serialisation

  5. serialisation is the process of translating data structures or object

    state into a format that can be stored or transmitted and reconstructed later. — Wikipedia, obvs
  6. JSON { "name": "2D Apple Games by Tutorials", "sku": "igt1",

    "image_url": "\/a725405c-a26a-4974-bcb0-d7fdef766f99.png", "url": "\/products\/2d-apple-games-by-tutorials" } Swift struct Product { let name: String let image_url: URL? let url: URL? let sku: String }
  7. dynamic languages

  8. can construct model objects at runtime

  9. Ruby product = JSON.parse(json_string, object_class: OpenStruct)

  10. or you can use introspection (reflection)

  11. static languages

  12. introspection still an option

  13. C̅ Product deserializedProduct = JsonConvert.DeserializeObject<Product>(jsonString);

  14. reflection in Swift isn't as powerful

  15. Naïve Parsing1 var repos = [Repo]() if let json :

    AnyObject = json { if let array = json as? NSArray { for jsonItem in array as [AnyObject] { if let id = jsonItem.valueForKey("id") as? Int { if let name = jsonItem.valueForKey("name") as? String { if let url_string = jsonItem.valueForKey("url") as? String { if let fork = jsonItem.valueForKey("fork") as? Bool { if let url = NSURL(string: url_string) { let description = jsonItem.valueForKey("description") as? String var homepage: NSURL? = .None if let homepage_string = jsonItem.valueForKey("homepage") as? String { homepage = NSURL(string: homepage_string) } let repo = Repo(id: id, name: name, desc: description, url: url, homepage: homepage, fork: fork) repos += [repo] } } } } } } } } 1 This Swift is 2.5 years old
  16. SwiftyJSON2 let json = JSON(data: rawJSON!, options: .allZeros, error: nil)

    var repos = [Repo]() for (index: String, subJson: JSON) in json { if let id = subJson["id"].int, let name = subJson["name"].string, let url = subJson["url"].string, let fork = subJson["fork"].bool { var homepage: NSURL? = .None if let homepage_raw = subJson["homepage"].string { homepage = NSURL(string: homepage_raw) } let url_url = NSURL(string: url)! repos += [Repo(id: id, name: name, desc: subJson["description"].string, url: url_url, homepage: homepage, fork: fork)] } } 2 It's from a blog I wrote about different JSON parsing options in Swift.
  17. Argo3 extension Repo: JSONDecodable { static func create(id: Int)(name: String)(desc:

    String?) (url: NSURL)(homepage: NSURL?)(fork: Bool) -> Repo { return Repo(id: id, name: name, desc: desc, url: url, homepage: homepage, fork: fork) } static func decode(j: JSON) -> Repo? { return Repo.create <^> j <| "id" <*> j <| "name" <*> j <|? "description" <*> j <| "url" <*> j <|? "homepage" <*> j <| "fork" } } let repos: [Repo]? = (JSONValue.parse <^> json) >>- decodeArray 3 Don't use any of them. Read the blog here: http://blog.scottlogic.com/2015/03/09/json-in-swift.html.
  18. enter Codable

  19. compiler generated extensions

  20. 1.

  21. 1. adopt Codable protocol

  22. 2.

  23. 2. done! (probably)

  24. demo

  25. JSON

  26. None
  27. None
  28. None
  29. demo

  30. Encodable public protocol Encodable { public func encode(to encoder: Encoder)

    throws }
  31. Encoder public protocol Encoder { .... public func container<Key>(keyedBy type:

    Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey public func unkeyedContainer() -> UnkeyedEncodingContainer public func singleValueContainer() -> SingleValueEncodingContainer }
  32. None
  33. None
  34. None
  35. None
  36. Decodable public protocol Decodable { public init(from decoder: Decoder) throws

    }
  37. Decoder public protocol Decoder { ... public func container<Key>(keyedBy type:

    Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey public func unkeyedContainer() throws -> UnkeyedDecodingContainer public func singleValueContainer() throws -> SingleValueDecodingContainer }
  38. demo

  39. unlike other iOS 11 guff...

  40. you can use this NOW

  41. well, once you migrate to Swift 4

  42. i like it. you should try it.

  43. Some Links from Clever People — swiftunboxed.com/stdlib/json-encoder-encodable/ — swiftunboxed.com/stdlib/json-decoder-decodable/ —

    mikeash.com/pyblog/friday-qa-2017-07-14- swiftcodable.html — mikeash.com/pyblog/friday-qa-2017-07-28-a-binary- coder-for-swift.html — lists.swift.org/pipermail/swift-evolution/Week-of- Mon-20170731/038522.html
  44. github.com/sammyd /iOSConfSG2017_Codable — @iwantmyrealname