type-safe web apis with protocol buffers in swift
TRANSCRIPT
Type-safe Web APIs with Protocol Buffers in Swift
1 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Hi, I'm Yusuke@kitasuke
2 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
I'm going to talk about...→ What Protocol Buffers are
3 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
I'm going to talk about...→ What Protocol Buffers are
→ Pros and Cons
4 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
I'm going to talk about...→ What Protocol Buffers are
→ Pros and Cons→ Where to start
5 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Web APIs6 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
JSON7 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP RequestJSON ➡ Data
8 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
let json = ["id": 1]let data = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
var request = URLRequest(url: url)request.httpBody = data
9 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP ResponseData ➡ JSON
10 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
// {"user": {"name": "Yusuke"}}URLSession.shared.dataTask(with: request) { (data, _, _) in let json = (try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)) as? [AnyHashable: Any] let user = json?["user"] as? [AnyHashable: Any] let name = user?["name"] as? String}
11 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
{"isTyped": false, "status": "disappointed"}
12 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
[AnyHashable: Any]
13 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Any?
14 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
!
15 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
ProtocolBuffers
a.k.a protobuf16 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for
serializing structured data – think XML, but smaller, faster, and simpler.
17 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Serialization format- think JSON, but
smaller, faster and safer— Yusuke
18 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Serialization Format
19 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Why are Protocol Buffers a big deal?
20 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP RequestJSON ➡ Data
21 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
let json = ["id": 1]let data = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
var request = URLRequest(url: url)request.httpBody = data
22 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP RequestJSON ➡ Data
23 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP RequestUserRequest ➡ Data
24 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
// custom typelet userRequest = UserRequest.with { $0.id = 1}let body = try? body.serializedData()
var request = URLRequest(url: url)request.httpBody = body
25 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP ResponseData ➡ JSON
26 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
// {"user": {"name": "Yusuke"}}URLSession.shared.dataTask(with: request) { (data, _, _) in let json = (try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)) as? [AnyHashable: Any] let user = json?["user"] as? [AnyHashable: Any] let name = user?["name"] as? String}
27 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP ResponseData ➡ JSON
28 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP ResponseData ➡ UserResponse
29 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
// UserResponse(user: User(name: "Yusuke"))URLSession.shared.dataTask(with: request) { (data, _, _) in // custom type guard let response: UserResponse = try? UserResponse(serializedData: data!) else { // error return } let user = response.user let name = user.name}
30 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Protobuf( isTyped: true, status: .satisfied)
31 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
!
32 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
But how do they work?
33 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
protobuf for Swiftapple/swift-protobuf
34 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
"But we still use Objective-C !"
35 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
protobufgoogle/protobuf
36 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
1. Define message types2. Generate code
3. Serialize/Deserialize
37 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
1. Define message types2. Generate code
3. Serialize/Deserialize
38 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Message types define data structures
in .proto files
39 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Message types have key-value pairs
40 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
41 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
user.proto
syntax = "proto3"; // protoc version
message User { int32 id = 1; // field number string name = 2; string introduction = 3; string photoUrl = 4; ParticipantType participantType = 5;
enum ParticipantType { Speaker = 0; Attendee = 1; }}
42 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
talk.proto
syntax = "proto3";
import "user.proto";
message Talk { int32 id = 1; string title = 2; string desc = 3; User speaker = 4; repeated string tags = 5; // Array}
43 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
1. Define message types2. Generate code
3. Serialize/Deserialize
44 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
protobuf compiler generates code from .proto file
45 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Basic typesInt32, UInt32, Int64, UInt64, Bool, Float, Double, String,
Array, Dictionary, Data
46 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Supported languagesC, C++, C#, Erlang, Go, Haskell, Java, Javascript, Objective-C, Perl, PHP, Python, Ruby, Rust, Scala,
Swift etc.
47 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Swift features→ struct, not class
→ enum RawValue is Int→ Default value is set
48 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
49 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
user.protosyntax = "proto3"; // protoc version
message User { int32 id = 1; // field number string name = 2; string introduction = 3; string photoUrl = 4; ParticipantType participantType = 5;
enum ParticipantType { Speaker = 0; Attendee = 1; }}
50 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
user.pb.swift// structstruct User: SwiftProtobuf.Message, ... { init() {}
enum Type: SwiftProtobuf.Enum { typealias RawValue = Int // always Int case speaker // = 0 case participant // = 1 case UNRECOGNIZED(Int) }
// property has default value var id: Int32 = 0 var name: String = "" var introduction: String = "" var photoURL: String = "" var participantType: User.ParticipantType = .speaker}
51 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
talk.proto
syntax = "proto3";
import "user.proto";
message Talk { int32 id = 1; string title = 2; string desc = 3; User speaker = 4; repeated string tags = 5; // Array}
52 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
talk.pb.swift
struct Talk: SwiftProtobuf.Message, ... { init() {}
var id: Int32 = 0 var title: String = "" var speaker: User = User() var desc: String = "" var tags: [String] = []}
53 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
54 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
User.javapublic static final class User extends Message<User, User.Builder> { public final Integer id; public final String name; public final String introduction; public final String photoUrl; public final ParticipantType participantType;}
55 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Talk.java
public final class Talk extends Message<Talk, Talk.Builder> { public final Integer id; public final String title; public final User speaker; public final String summary; public final List<String> tags;}
56 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
57 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
user.pb.gotype User_Type int32
const ( User_Speaker User_ParticipantType = 0 User_Attendee User_ParticipantType = 1)
type User struct { ID int32 ˆprotobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"ˆ Name string ˆprotobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"ˆ Introduction string ˆprotobuf:"bytes,3,opt,name=introduction,proto3" json:"introduction,omitempty"ˆ PhotoURL string ˆprotobuf:"bytes,4,opt,name=photoUrl,proto3" json:"photoUrl,omitempty"ˆ Type User_Type ˆprotobuf:"varint,5,opt,name=type,proto3,enum=api.User_Type" json:"type,omitempty"ˆ}
58 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
talk.pb.gotype Talk struct { ID int32 ˆprotobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"ˆ Title string ˆprotobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"ˆ Speaker *User ˆprotobuf:"bytes,3,opt,name=speaker" json:"speaker,omitempty"ˆ Summary string ˆprotobuf:"bytes,4,opt,name=summary,proto3" json:"summary,omitempty"ˆ Tags []string ˆprotobuf:"bytes,5,rep,name=tags" json:"tags,omitempty"ˆ}
59 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
One message type⬇
Multiple languages code60 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Less communication, More collaboration
with other platforms
61 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
1. Define message types2. Generate source files3. Serialize/Deserialize
62 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Serializationpublic func serializedData(partial: Bool = default) throws -> Data
public func jsonString() throws -> String
public func textFormatString() throws -> String
63 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
let user = User.with { $0.id = 1 $0.type = .speaker $0.name = "kitasuke"}
let talk = Talk.with { $0.id = 1 $0.title = "Type-safe Web APIs with Protocol Buffers in Swift" $0.speaker = user $0.tags = ["swift", "iOS", "protocol-buffers", "ioscon", "type-safe"]}
let data = try? talk.serializedData()
64 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Deserializationpublic convenience init(serializedData data: Data, extensions: SwiftProtobuf.ExtensionSet? = default, partial: Bool = default) throws
public convenience init(jsonString: String) throws
public convenience init(textFormatString: String, extensions: SwiftProtobuf.ExtensionSet? = default) throws
65 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
let talk = try? Talk(serializedData: data)
let title = talk?.titlelet speaker = talk?.speakerlet tags = talk?.tags
66 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
How serialization works
67 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Binary Encoding
68 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Key factor1. Field number
2. Wire type
69 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Field numbermessage Talk { int32 id = 1; ← // Field number string title = 2; string desc = 3; User speaker = 4; repeated string tags = 5;}
70 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Wire typeType Meaning Used For0 Varint int32, int64, uint32, uint64,
sint32, sint64, bool, enum1 64-bit fixed64, sfixed64, double2 Length-delimited string, bytes, embedded
messages, packed repeated fields
3 (deprecated)4 (deprecated)5 32-bit fixed32, sfix3d32, float
71 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
// message typemessage Test1 { int32 a = 1;}test1.a = 300
// encoded message08 96 01
08 // field number and wire type96 01 // value which is 300
72 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
So small and numeric
73 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
High network performance
74 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Demokitasuke/SwiftProtobufSample
75 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Quick Recap76 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Quick Recap→ Type-safety
77 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Quick Recap→ Type-safety
→ Shared data model
78 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Quick Recap→ Type-safety
→ Shared data model→ High performance
79 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
You might have concerns about...
80 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Versioning81 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Backward compatibility→ Unknown field is ignored
→ Default value for missing field
82 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Backward compatibility→ Unknown field is ignored
→ Default value for missing field
as long as you don't change existing field number or wire type
83 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Coexistence ofprotobuf & JSON
84 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Absolutely you can!
85 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Accept & Content-Type
→ application/protobuf - protobuf→ application/json - JSON
86 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP Requestvar request = URLRequest(url: url)if protobuf { request.setValue("application/protobuf", forHTTPHeaderField: "Content-Type") request.setValue("application/protobuf", forHTTPHeaderField: "Accept")} else if json { request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("application/json", forHTTPHeaderField: "Accept")}
87 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
HTTP ResponseURLSession.shared.dataTask(with: request) { (data, urlResponse, _) in let httpURLResponse = urlResponse as? HTTPURLResponse let contentType = httpURLResponse?.allHeaderFields["Content-Type"] as? String
if contentType == "application/protobuf" { let response = try? Response(serializedData: data!) } else if contentType == "application/json" { let response = try? Response(jsonString: data!) }}
88 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Sounds goodso far !
89 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
So, what are Cons?
90 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Not human-readable→ Binary data is not understandable
91 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Time investment→ Time consuming at the beginning→ Involvement from other platforms
92 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Swift version→ Watch Swift version of protobuf plugin
→ Specify tag version if you use older version
93 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Stability→ Still pre-release version only for Swift ⚠
→ Contribute if you find a bug !
94 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Where should we start?
95 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Internal service
→ Easy to adapt→ Small start
96 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Data store
→ Database→ NSKeyedArchiver
→ NSCache
97 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Parsing library
→ JSON parser→ Server side Swift
98 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Conclusion99 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Conclusion→ Swifty
100 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Conclusion→ Swifty
→ Consistent in Cross-platform
101 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Conclusion→ Swifty
→ Consistent in Cross-platform→ Extensible
102 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
It's definitely worth it !
103 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Partially in Production70M Downloads
!"#
104 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
CreditsProtocol Buffersswift-protobuf
KituraProtocol Buffers in your Kitura Apps
105 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017
Thank you!GitHub: https://github.com/kitasuke
Demo: SwiftProtobufSampleTwitter: @kitasuke
Email: [email protected]
106 — Type-safe Web APIs with Protocol Buffers in Swift, Yusuke Kita (@kitasuke), iOSCon 2017