Slide 1

Slide 1 text

Decoding Codable

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

@iwantmyrealname github.com/sammyd

Slide 4

Slide 4 text

serialisation

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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 }

Slide 7

Slide 7 text

dynamic languages

Slide 8

Slide 8 text

can construct model objects at runtime

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

or you can use introspection (reflection)

Slide 11

Slide 11 text

static languages

Slide 12

Slide 12 text

introspection still an option

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

reflection in Swift isn't as powerful

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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.

Slide 17

Slide 17 text

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.

Slide 18

Slide 18 text

enter Codable

Slide 19

Slide 19 text

compiler generated extensions

Slide 20

Slide 20 text

1.

Slide 21

Slide 21 text

1. adopt Codable protocol

Slide 22

Slide 22 text

2.

Slide 23

Slide 23 text

2. done! (probably)

Slide 24

Slide 24 text

demo

Slide 25

Slide 25 text

JSON

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

demo

Slide 30

Slide 30 text

Encodable public protocol Encodable { public func encode(to encoder: Encoder) throws }

Slide 31

Slide 31 text

Encoder public protocol Encoder { .... public func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key : CodingKey public func unkeyedContainer() -> UnkeyedEncodingContainer public func singleValueContainer() -> SingleValueEncodingContainer }

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Decodable public protocol Decodable { public init(from decoder: Decoder) throws }

Slide 37

Slide 37 text

Decoder public protocol Decoder { ... public func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer where Key : CodingKey public func unkeyedContainer() throws -> UnkeyedDecodingContainer public func singleValueContainer() throws -> SingleValueDecodingContainer }

Slide 38

Slide 38 text

demo

Slide 39

Slide 39 text

unlike other iOS 11 guff...

Slide 40

Slide 40 text

you can use this NOW

Slide 41

Slide 41 text

well, once you migrate to Swift 4

Slide 42

Slide 42 text

i like it. you should try it.

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

github.com/sammyd /iOSConfSG2017_Codable — @iwantmyrealname