-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathContents.swift
213 lines (189 loc) · 6.33 KB
/
Contents.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//: [Previous Topic](@previous)
/*:
# Playground for Presenting
# Handling Error while ecoding and decoding in `Codable`
*/
//: ### handling occured error while try to decode from json string into dataType
//: ### we create a simple mistake which write a wrong key name in `CodingKeys` enum in `Message` struct
//: ### then we write a non optional property in message called `update` as `TimeInterval`
//: ### which json key maybe have a value in json string
//: ### you can produce error by reading
//: [Apple DecodingError Document](https://developer.apple.com/documentation/swift/decodingerror/)
//: ### and reading
//: [Apple EncodingError Document](https://developer.apple.com/documentation/swift/encodingerror/)
/*:
A Message JSON Object
```
{
"message": "Hi, How are you?",
"create": 1523895892938,
"update": 1523899532938, maybe has a value in json otherwise filled with `null`
"from": {
"name" : "Ali",
"age":25,
"email":"[email protected]",
"address":"Iran, Tehran"
}
}
```
*/
import Foundation
//:1. Create A simple json `Data` from `JSON` String
let jsonMessageData = """
{
"message": "Hi, How are you?",
"create": 1523895892938,
"from": {
"name" : "Ali",
"age":25,
"email":"[email protected]",
"address":"Iran, Tehran"
}
}
""".data(using: .utf8)!
//:2. Define a struct and called Message which adapt to `Codable` Protocol
struct Message : Codable {
let message : String
let create : TimeInterval
let sender : Person
/*:
3. Declared CodingKeys\
which is `enum` of `String` and adapt to `CodingKey` protocol\
*/
private enum CodingKeys : String, CodingKey {
//: * message represent of *message* property
case message
//: * create represent of *create* property
case create
/*:
* sender represent of *sender* property but\
we need to set value of *sender* case to "from"\
**Note:**"from" is json key that present in message json string
## *we just need to set a wrong key name which we set it to 'fromPerson' to occur error*
*/
case sender = "fromPerson"
}
//:4. Define a nested struct and named Person which adapted to `Codable` Protocol
struct Person : Codable {
let name : String
let age : Int
let email : String
let address : String
}
}
//:5. defind jsonDecoder as JSONDecoder
let jsonDecoder = JSONDecoder()
do {
/*:
6. we use `-decode` method to decode `jsonData` into `Message` object with `try` option
- first parameter is type of Object which want convert into such as `Int`, `String`,
or Declared `struct` or `class`. The example is `Int.self`
- second parameter is `jsonData' which we want convert from it into our definded type
*/
let message = try jsonDecoder.decode(Message.self,from:jsonMessageData)
//:7. print Decoded `Message` Object
print("""
message = \(message.message)
create = \(message.create)
sender = \(message.sender)
\n
""")
} catch {
/*:
8. Handling Error
* error occured while decoding json to message swift struct
*/
print("Error on decoding \(error)")
}
/*:
9. So we can write above code again but handling `DecodingError.keyNotFound`\
other solution is to make sender optional then error does not happened\
```let sender : Person?```
*/
do {
let message = try jsonDecoder.decode(Message.self,from:jsonMessageData)
print("""
message = \(message.message)
create = \(message.create)
sender = \(message.sender)
\n
""")
} catch DecodingError.keyNotFound(let key, let context) {
//:## `DecodingError.keyNotFound` error catch here
print("key is not found in json for keyPath : \(key)")
print("for context = \(context.debugDescription)")
print("CodingPath = \(context.codingPath)")
} catch {
//: other error will catch here
print("Error on decoding \(error)")
}
//: ### a key maybe present is json or isn't
//:1. Create A simple json `Data` from `JSON` String which key 'update' has `null` value
let jsonMessageUpdateData = """
{
"message": "Hi, How are you?",
"create": 1523895892938,
"update": null,
"from": {
"name" : "Ali",
"age":25,
"email":"[email protected]",
"address":"Iran, Tehran"
}
}
""".data(using: .utf8)!
//:2. Define a struct and called Message2 which adapt to `Codable` Protocol
struct Message2 : Codable {
let message : String
let create : TimeInterval
let update : TimeInterval
let sender : Person
/*:
3. Declared CodingKeys\
which is `enum` of `String` and adapt to `CodingKey` protocol\
*/
private enum CodingKeys : String, CodingKey {
case message
case create
case update
case sender = "from"
}
//:4. Define a nested struct and named Person which adapted to `Codable` Protocol
struct Person : Codable {
let name : String
let age : Int
let email : String
let address : String
}
}
/*:
5. if we want try to decoding `jsonMessageData` to `Message2` Object \
we meet `DecodingError.valueNotFound` error while decoding data\
**solution**: we just need set update property to optional `TimeInterval`\
```let update: TimeInterval?```
*/
do {
//: this line code occur error because `update` key has `null` value in jsonMessageUpdateData
let message = try jsonDecoder.decode(Message2.self,from:jsonMessageUpdateData)
print("""
message = \(message.message)
create = \(message.create)
update = \(message.update)
sender = \(message.sender)
\n
""")
} catch DecodingError.keyNotFound(let key, let context) {
//:## `DecodingError.keyNotFound` error catch here
print("key is not found in json for keyPath : \(key)")
print("for context = \(context.debugDescription)")
print("CodingPath = \(context.codingPath)")
} catch DecodingError.valueNotFound(let type,let context){
//:## `DecodingError.valueNotFound` error catch here
print("value not found in json for type : \(type)")
print("for context = \(context.debugDescription)")
print("CodingPath = \(context.codingPath)")
} catch {
//: other error will catch here
print("Error on decoding \(error)")
}
//: [Next Topic](@next)