Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
# SwiftyJSON
2
 
3
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![CocoaPods](https://img.shields.io/cocoapods/v/SwiftyJSON.svg) ![Platform](https://img.shields.io/badge/platforms-iOS%208.0%20%7C%20macOS%2010.10%20%7C%20tvOS%209.0%20%7C%20watchOS%203.0-F28D00.svg) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
4
 
5
SwiftyJSON makes it easy to deal with JSON data in Swift.
6
 
7
Platform | Build Status
8
---------| --------------|
9
*OS      | [![Travis CI](https://travis-ci.org/SwiftyJSON/SwiftyJSON.svg?branch=master)](https://travis-ci.org/SwiftyJSON/SwiftyJSON)    |
10
[Linux](https://github.com/IBM-Swift/SwiftyJSON)      | [![Build Status](https://travis-ci.org/IBM-Swift/SwiftyJSON.svg?branch=master)](https://travis-ci.org/IBM-Swift/SwiftyJSON)     |
11
 
12
 
13
1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good)
14
2. [Requirements](#requirements)
15
3. [Integration](#integration)
16
4. [Usage](#usage)
17
   - [Initialization](#initialization)
18
   - [Subscript](#subscript)
19
   - [Loop](#loop)
20
   - [Error](#error)
21
   - [Optional getter](#optional-getter)
22
   - [Non-optional getter](#non-optional-getter)
23
   - [Setter](#setter)
24
   - [Raw object](#raw-object)
25
   - [Literal convertibles](#literal-convertibles)
26
   - [Merging](#merging)
27
5. [Work with Alamofire](#work-with-alamofire)
28
6. [Work with Moya](#work-with-moya)
29
7. [SwiftyJSON Model Generator](#swiftyjson-model-generator)
30
 
31
> [中文介绍](http://tangplin.github.io/swiftyjson/)
32
 
33
 
34
## Why is the typical JSON handling in Swift NOT good?
35
 
36
Swift is very strict about types. But although explicit typing is good for saving us from mistakes, it becomes painful when dealing with JSON and other areas that are, by nature, implicit about types.
37
 
38
Take the Twitter API for example. Say we want to retrieve a user's "name" value of some tweet in Swift (according to [Twitter's API](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline)).
39
 
40
The code would look like this:
41
 
42
```swift
43
if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
44
    let user = statusesArray[0]["user"] as? [String: Any],
45
    let username = user["name"] as? String {
46
    // Finally we got the username
47
}
48
```
49
 
50
It's not good.
51
 
52
Even if we use optional chaining, it would be messy:
53
 
54
```swift
55
if let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
56
    let username = (JSONObject[0]["user"] as? [String: Any])?["name"] as? String {
57
        // There's our username
58
}
59
```
60
 
61
An unreadable mess--for something that should really be simple!
62
 
63
With SwiftyJSON all you have to do is:
64
 
65
```swift
66
let json = JSON(data: dataFromNetworking)
67
if let userName = json[0]["user"]["name"].string {
68
  //Now you got your value
69
}
70
```
71
 
72
And don't worry about the Optional Wrapping thing. It's done for you automatically.
73
 
74
```swift
75
let json = JSON(data: dataFromNetworking)
76
let result = json[999999]["wrong_key"]["wrong_name"]
77
if let userName = result.string {
78
    //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
79
} else {
80
    //Print the error
81
    print(result.error)
82
}
83
```
84
 
85
## Requirements
86
 
87
- iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+
88
- Xcode 8
89
 
90
## Integration
91
 
92
#### CocoaPods (iOS 8+, OS X 10.9+)
93
 
94
You can use [CocoaPods](http://cocoapods.org/) to install `SwiftyJSON` by adding it to your `Podfile`:
95
 
96
```ruby
97
platform :ios, '8.0'
98
use_frameworks!
99
 
100
target 'MyApp' do
101
    pod 'SwiftyJSON', '~> 4.0'
102
end
103
```
104
 
105
#### Carthage (iOS 8+, OS X 10.9+)
106
 
107
You can use [Carthage](https://github.com/Carthage/Carthage) to install `SwiftyJSON` by adding it to your `Cartfile`:
108
 
109
```
110
github "SwiftyJSON/SwiftyJSON" ~> 4.0
111
```
112
 
113
If you use Carthage to build your dependencies, make sure you have added `SwiftyJSON.framework` to the "Linked Frameworks and Libraries" section of your target, and have included them in your Carthage framework copying build phase.
114
 
115
#### Swift Package Manager
116
 
117
You can use [The Swift Package Manager](https://swift.org/package-manager) to install `SwiftyJSON` by adding the proper description to your `Package.swift` file:
118
 
119
```swift
120
// swift-tools-version:4.0
121
import PackageDescription
122
 
123
let package = Package(
124
    name: "YOUR_PROJECT_NAME",
125
    dependencies: [
126
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),
127
    ]
128
)
129
```
130
Then run `swift build` whenever you get prepared.
131
 
132
#### Manually (iOS 7+, OS X 10.9+)
133
 
134
To use this library in your project manually you may:
135
 
136
1. for Projects, just drag SwiftyJSON.swift to the project tree
137
2. for Workspaces, include the whole SwiftyJSON.xcodeproj
138
 
139
## Usage
140
 
141
#### Initialization
142
 
143
```swift
144
import SwiftyJSON
145
```
146
 
147
```swift
148
let json = JSON(data: dataFromNetworking)
149
```
150
Or
151
 
152
```swift
153
let json = JSON(jsonObject)
154
```
155
Or
156
 
157
```swift
158
if let dataFromString = jsonString.data(using: .utf8, allowLossyConversion: false) {
159
    let json = JSON(data: dataFromString)
160
}
161
```
162
 
163
#### Subscript
164
 
165
```swift
166
// Getting a double from a JSON Array
167
let name = json[0].double
168
```
169
 
170
```swift
171
// Getting an array of string from a JSON Array
172
let arrayNames =  json["users"].arrayValue.map {$0["name"].stringValue}
173
```
174
 
175
```swift
176
// Getting a string from a JSON Dictionary
177
let name = json["name"].stringValue
178
```
179
 
180
```swift
181
// Getting a string using a path to the element
182
let path: [JSONSubscriptType] = [1,"list",2,"name"]
183
let name = json[path].string
184
// Just the same
185
let name = json[1]["list"][2]["name"].string
186
// Alternatively
187
let name = json[1,"list",2,"name"].string
188
```
189
 
190
```swift
191
// With a hard way
192
let name = json[].string
193
```
194
 
195
```swift
196
// With a custom way
197
let keys:[JSONSubscriptType] = [1,"list",2,"name"]
198
let name = json[keys].string
199
```
200
 
201
#### Loop
202
 
203
```swift
204
// If json is .Dictionary
205
for (key,subJson):(String, JSON) in json {
206
   // Do something you want
207
}
208
```
209
 
210
*The first element is always a String, even if the JSON is an Array*
211
 
212
```swift
213
// If json is .Array
214
// The `index` is 0..<json.count's string value
215
for (index,subJson):(String, JSON) in json {
216
    // Do something you want
217
}
218
```
219
 
220
#### Error
221
 
222
##### SwiftyJSON 4.x
223
 
224
SwiftyJSON 4.x introduces an enum type called `SwiftyJSONError`, which includes `unsupportedType`, `indexOutOfBounds`, `elementTooDeep`, `wrongType`, `notExist` and `invalidJSON`, at the same time, `ErrorDomain` are being replaced by `SwiftyJSONError.errorDomain`.
225
Note: Those old error types are deprecated in SwiftyJSON 4.x and will be removed in the future release.
226
 
227
##### SwiftyJSON 3.x
228
 
229
Use a subscript to get/set a value in an Array or Dictionary
230
 
231
If the JSON is:
232
*  an array, the app may crash with "index out-of-bounds."
233
*  a dictionary, it will be assigned to `nil` without a reason.
234
*  not an array or a dictionary, the app may crash with an "unrecognised selector" exception.
235
 
236
This will never happen in SwiftyJSON.
237
 
238
```swift
239
let json = JSON(["name", "age"])
240
if let name = json[999].string {
241
    // Do something you want
242
} else {
243
    print(json[999].error!) // "Array[999] is out of bounds"
244
}
245
```
246
 
247
```swift
248
let json = JSON(["name":"Jack", "age": 25])
249
if let name = json["address"].string {
250
    // Do something you want
251
} else {
252
    print(json["address"].error!) // "Dictionary["address"] does not exist"
253
}
254
```
255
 
256
```swift
257
let json = JSON(12345)
258
if let age = json[0].string {
259
    // Do something you want
260
} else {
261
    print(json[0])       // "Array[0] failure, It is not an array"
262
    print(json[0].error!) // "Array[0] failure, It is not an array"
263
}
264
 
265
if let name = json["name"].string {
266
    // Do something you want
267
} else {
268
    print(json["name"])       // "Dictionary[\"name"] failure, It is not an dictionary"
269
    print(json["name"].error!) // "Dictionary[\"name"] failure, It is not an dictionary"
270
}
271
```
272
 
273
#### Optional getter
274
 
275
```swift
276
// NSNumber
277
if let id = json["user"]["favourites_count"].number {
278
   // Do something you want
279
} else {
280
   // Print the error
281
   print(json["user"]["favourites_count"].error!)
282
}
283
```
284
 
285
```swift
286
// String
287
if let id = json["user"]["name"].string {
288
   // Do something you want
289
} else {
290
   // Print the error
291
   print(json["user"]["name"].error!)
292
}
293
```
294
 
295
```swift
296
// Bool
297
if let id = json["user"]["is_translator"].bool {
298
   // Do something you want
299
} else {
300
   // Print the error
301
   print(json["user"]["is_translator"].error!)
302
}
303
```
304
 
305
```swift
306
// Int
307
if let id = json["user"]["id"].int {
308
   // Do something you want
309
} else {
310
   // Print the error
311
   print(json["user"]["id"].error!)
312
}
313
...
314
```
315
 
316
#### Non-optional getter
317
 
318
Non-optional getter is named `xxxValue`
319
 
320
```swift
321
// If not a Number or nil, return 0
322
let id: Int = json["id"].intValue
323
```
324
 
325
```swift
326
// If not a String or nil, return ""
327
let name: String = json["name"].stringValue
328
```
329
 
330
```swift
331
// If not an Array or nil, return []
332
let list: Array<JSON> = json["list"].arrayValue
333
```
334
 
335
```swift
336
// If not a Dictionary or nil, return [:]
337
let user: Dictionary<String, JSON> = json["user"].dictionaryValue
338
```
339
 
340
#### Setter
341
 
342
```swift
343
json["name"] = JSON("new-name")
344
json[0] = JSON(1)
345
```
346
 
347
```swift
348
json["id"].int =  1234567890
349
json["coordinate"].double =  8766.766
350
json["name"].string =  "Jack"
351
json.arrayObject = [1,2,3,4]
352
json.dictionaryObject = ["name":"Jack", "age":25]
353
```
354
 
355
#### Raw object
356
 
357
```swift
358
let rawObject: Any = json.object
359
```
360
 
361
```swift
362
let rawValue: Any = json.rawValue
363
```
364
 
365
```swift
366
//convert the JSON to raw NSData
367
do {
368
	let rawData = try json.rawData()
369
  //Do something you want
370
} catch {
371
	print("Error \(error)")
372
}
373
```
374
 
375
```swift
376
//convert the JSON to a raw String
377
if let rawString = json.rawString() {
378
  //Do something you want
379
} else {
380
	print("json.rawString is nil")
381
}
382
```
383
 
384
#### Existence
385
 
386
```swift
387
// shows you whether value specified in JSON or not
388
if json["name"].exists()
389
```
390
 
391
#### Literal convertibles
392
 
393
For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/)
394
 
395
```swift
396
// StringLiteralConvertible
397
let json: JSON = "I'm a json"
398
```
399
 
400
```swift
401
/ /IntegerLiteralConvertible
402
let json: JSON =  12345
403
```
404
 
405
```swift
406
// BooleanLiteralConvertible
407
let json: JSON =  true
408
```
409
 
410
```swift
411
// FloatLiteralConvertible
412
let json: JSON =  2.8765
413
```
414
 
415
```swift
416
// DictionaryLiteralConvertible
417
let json: JSON =  ["I":"am", "a":"json"]
418
```
419
 
420
```swift
421
// ArrayLiteralConvertible
422
let json: JSON =  ["I", "am", "a", "json"]
423
```
424
 
425
```swift
426
// With subscript in array
427
var json: JSON =  [1,2,3]
428
json[0] = 100
429
json[1] = 200
430
json[2] = 300
431
json[999] = 300 // Don't worry, nothing will happen
432
```
433
 
434
```swift
435
// With subscript in dictionary
436
var json: JSON =  ["name": "Jack", "age": 25]
437
json["name"] = "Mike"
438
json["age"] = "25" // It's OK to set String
439
json["address"] = "L.A." // Add the "address": "L.A." in json
440
```
441
 
442
```swift
443
// Array & Dictionary
444
var json: JSON =  ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]]
445
json["list"][3]["what"] = "that"
446
json["list",3,"what"] = "that"
447
let path: [JSONSubscriptType] = ["list",3,"what"]
448
json[path] = "that"
449
```
450
 
451
```swift
452
// With other JSON objects
453
let user: JSON = ["username" : "Steve", "password": "supersecurepassword"]
454
let auth: JSON = [
455
  "user": user.object, // use user.object instead of just user
456
  "apikey": "supersecretapitoken"
457
]
458
```
459
 
460
#### Merging
461
 
462
It is possible to merge one JSON into another JSON. Merging a JSON into another JSON adds all non existing values to the original JSON which are only present in the `other` JSON.
463
 
464
If both JSONs contain a value for the same key, _mostly_ this value gets overwritten in the original JSON, but there are two cases where it provides some special treatment:
465
 
466
- In case of both values being a `JSON.Type.array` the values form the array found in the `other` JSON getting appended to the original JSON's array value.
467
- In case of both values being a `JSON.Type.dictionary` both JSON-values are getting merged the same way the encapsulating JSON is merged.
468
 
469
In case, where two fields in a JSON have a different types, the value will get always overwritten.
470
 
471
There are two different fashions for merging: `merge` modifies the original JSON, whereas `merged` works non-destructively on a copy.
472
 
473
```swift
474
let original: JSON = [
475
    "first_name": "John",
476
    "age": 20,
477
    "skills": ["Coding", "Reading"],
478
    "address": [
479
        "street": "Front St",
480
        "zip": "12345",
481
    ]
482
]
483
 
484
let update: JSON = [
485
    "last_name": "Doe",
486
    "age": 21,
487
    "skills": ["Writing"],
488
    "address": [
489
        "zip": "12342",
490
        "city": "New York City"
491
    ]
492
]
493
 
494
let updated = original.merge(with: update)
495
// [
496
//     "first_name": "John",
497
//     "last_name": "Doe",
498
//     "age": 21,
499
//     "skills": ["Coding", "Reading", "Writing"],
500
//     "address": [
501
//         "street": "Front St",
502
//         "zip": "12342",
503
//         "city": "New York City"
504
//     ]
505
// ]
506
```
507
 
508
## String representation
509
There are two options available:
510
- use the default Swift one
511
- use a custom one that will handle optionals well and represent `nil` as `"null"`:
512
```swift
513
let dict = ["1":2, "2":"two", "3": nil] as [String: Any?]
514
let json = JSON(dict)
515
let representation = json.rawString(options: [.castNilToNSNull: true])
516
// representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null}
517
```
518
 
519
## Work with [Alamofire](https://github.com/Alamofire/Alamofire)
520
 
521
SwiftyJSON nicely wraps the result of the Alamofire JSON response handler:
522
 
523
```swift
524
Alamofire.request(url, method: .get).validate().responseJSON { response in
525
    switch response.result {
526
    case .success(let value):
527
        let json = JSON(value)
528
        print("JSON: \(json)")
529
    case .failure(let error):
530
        print(error)
531
    }
532
}
533
```
534
 
535
We also provide an extension of Alamofire for serializing NSData to SwiftyJSON's JSON.
536
 
537
See: [Alamofire-SwiftyJSON](https://github.com/SwiftyJSON/Alamofire-SwiftyJSON)
538
 
539
 
540
## Work with [Moya](https://github.com/Moya/Moya)
541
 
542
SwiftyJSON parse data to JSON:
543
 
544
```swift
545
let provider = MoyaProvider<Backend>()
546
provider.request(.showProducts) { result in
547
    switch result {
548
    case let .success(moyaResponse):
549
        let data = moyaResponse.data
550
        let json = JSON(data: data) // convert network data to json
551
        print(json)
552
    case let .failure(error):
553
        print("error: \(error)")
554
    }
555
}
556
 
557
```
558
 
559
## SwiftyJSON Model Generator
560
Tools to generate SwiftyJSON Models
561
* [JSON Cafe](http://www.jsoncafe.com/)
562
* [JSON Export](https://github.com/Ahmed-Ali/JSONExport)