├── .gitignore ├── .swift-version ├── .travis.yml ├── LICENSE ├── Package.pins ├── Package.swift ├── Package@swift-4.2.swift ├── Package@swift-4.swift ├── Package@swift-5.swift ├── README.md ├── Sources └── SwiftyJSON │ ├── LclJSONSerialization.swift │ └── SwiftyJSON.swift └── Tests ├── LinuxMain.swift └── SwiftyJSONTests ├── ArrayTests.swift ├── BaseTests.swift ├── ComparableTests.swift ├── DictionaryTests.swift ├── Info-OSX.plist ├── Info-iOS.plist ├── Info-tvOS.plist ├── LiteralConvertibleTests.swift ├── NumberTests.swift ├── PerformanceTests.swift ├── PrintableTests.swift ├── RawRepresentableTests.swift ├── RawTests.swift ├── SequenceTypeTests.swift ├── StringTests.swift ├── SubscriptTests.swift └── Tests.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | SwiftyJSON.xcodeproj 4 | */build/* 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | *.hmap 19 | *.xccheckout 20 | 21 | #CocoaPods 22 | Pods 23 | 24 | #Carthage 25 | Carthage/Build 26 | .build -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.0.1 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Travis CI build file. 2 | 3 | # whitelist (branches that should be built) 4 | branches: 5 | only: 6 | - master 7 | - /^issue.*$/ 8 | 9 | # the matrix of builds should cover each combination of Swift version 10 | # and platform that is supported. The version of Swift used is specified 11 | # by .swift-version, unless SWIFT_SNAPSHOT is specified. 12 | matrix: 13 | include: 14 | - os: linux 15 | dist: xenial 16 | sudo: required 17 | services: docker 18 | env: DOCKER_IMAGE=swift:4.0.3 SWIFT_SNAPSHOT=4.0.3 19 | - os: linux 20 | dist: xenial 21 | sudo: required 22 | services: docker 23 | env: DOCKER_IMAGE=swift:4.1.3 SWIFT_SNAPSHOT=4.1.3 24 | - os: linux 25 | dist: xenial 26 | sudo: required 27 | services: docker 28 | env: DOCKER_IMAGE=swift:4.2.4 SWIFT_SNAPSHOT=4.2.4 29 | - os: linux 30 | dist: xenial 31 | sudo: required 32 | services: docker 33 | env: DOCKER_IMAGE=swift:5.0.1-xenial 34 | - os: linux 35 | dist: xenial 36 | sudo: required 37 | services: docker 38 | env: DOCKER_IMAGE=swift:5.0.1 SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT 39 | - os: osx 40 | osx_image: xcode9.2 41 | sudo: required 42 | env: SWIFT_SNAPSHOT=4.0.3 43 | - os: osx 44 | osx_image: xcode9.4 45 | sudo: required 46 | env: SWIFT_SNAPSHOT=4.1.2 JAZZY_ELIGIBLE=true 47 | - os: osx 48 | osx_image: xcode10.1 49 | sudo: required 50 | env: SWIFT_SNAPSHOT=4.2.1 51 | - os: osx 52 | osx_image: xcode10.2 53 | sudo: required 54 | # Pending Travis Xcode 11 image 55 | # - os: osx 56 | # osx_image: xcode11 57 | # sudo: required 58 | # env: SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT 59 | 60 | before_install: 61 | - git clone https://github.com/IBM-Swift/Package-Builder.git 62 | 63 | script: 64 | - ./Package-Builder/build-package.sh -projectDir $TRAVIS_BUILD_DIR 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ruoyu Fu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.pins: -------------------------------------------------------------------------------- 1 | { 2 | "autoPin": false, 3 | "pins": [], 4 | "version": 1 5 | } 6 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:3.1 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | /** 4 | * Copyright IBM Corporation 2016, 2017 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | **/ 18 | 19 | import PackageDescription 20 | 21 | let package = Package( 22 | name: "SwiftyJSON", 23 | dependencies: [] 24 | ) 25 | -------------------------------------------------------------------------------- /Package@swift-4.2.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | /** 4 | * Copyright IBM Corporation 2016, 2017 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | **/ 18 | 19 | import PackageDescription 20 | 21 | let package = Package( 22 | name: "SwiftyJSON", 23 | products: [ 24 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 25 | .library( 26 | name: "SwiftyJSON", 27 | targets: ["SwiftyJSON"] 28 | ) 29 | ], 30 | dependencies: [], 31 | targets: [ 32 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 33 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 34 | .target( 35 | name: "SwiftyJSON", 36 | dependencies: [] 37 | ), 38 | .testTarget( 39 | name: "SwiftyJSONTests", 40 | dependencies: ["SwiftyJSON"] 41 | ) 42 | ] 43 | ) 44 | -------------------------------------------------------------------------------- /Package@swift-4.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | /** 4 | * Copyright IBM Corporation 2016, 2017 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | **/ 18 | 19 | import PackageDescription 20 | 21 | let package = Package( 22 | name: "SwiftyJSON", 23 | products: [ 24 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 25 | .library( 26 | name: "SwiftyJSON", 27 | targets: ["SwiftyJSON"] 28 | ) 29 | ], 30 | dependencies: [], 31 | targets: [ 32 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 33 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 34 | .target( 35 | name: "SwiftyJSON", 36 | dependencies: [] 37 | ), 38 | .testTarget( 39 | name: "SwiftyJSONTests", 40 | dependencies: ["SwiftyJSON"] 41 | ) 42 | ] 43 | ) 44 | -------------------------------------------------------------------------------- /Package@swift-5.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | /** 4 | * Copyright IBM Corporation 2016, 2017 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | **/ 18 | 19 | import PackageDescription 20 | 21 | let package = Package( 22 | name: "SwiftyJSON", 23 | products: [ 24 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 25 | .library( 26 | name: "SwiftyJSON", 27 | targets: ["SwiftyJSON"] 28 | ) 29 | ], 30 | dependencies: [], 31 | targets: [ 32 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 33 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 34 | .target( 35 | name: "SwiftyJSON", 36 | dependencies: [] 37 | ), 38 | .testTarget( 39 | name: "SwiftyJSONTests", 40 | dependencies: ["SwiftyJSON"] 41 | ) 42 | ] 43 | ) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftyJSON [中文介绍](http://tangplin.github.io/swiftyjson/) 2 | 3 | 4 | SwiftyJSON makes it easy to deal with JSON data in Swift. 5 | 6 | 1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good) 7 | 1. [Requirements](#requirements) 8 | 1. [Integration](#integration) 9 | 1. [Usage](#usage) 10 | - [Initialization](#initialization) 11 | - [Subscript](#subscript) 12 | - [Loop](#loop) 13 | - [Error](#error) 14 | - [Optional getter](#optional-getter) 15 | - [Non-optional getter](#non-optional-getter) 16 | - [Setter](#setter) 17 | - [Raw object](#raw-object) 18 | - [Literal convertibles](#literal-convertibles) 19 | 1. [Work with Alamofire](#work-with-alamofire) 20 | 21 | ## Why is the typical JSON handling in Swift NOT good? 22 | 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. 23 | 24 | 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://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline). 25 | 26 | The code would look like this: 27 | 28 | ```swift 29 | 30 | if let statusesArray = try? NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]], 31 | let user = statusesArray[0]["user"] as? [String: AnyObject], 32 | let username = user["name"] as? String { 33 | // Finally we got the username 34 | } 35 | 36 | ``` 37 | 38 | It's not good. 39 | 40 | Even if we use optional chaining, it would be messy: 41 | 42 | ```swift 43 | 44 | if let JSONObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]], 45 | let username = (JSONObject[0]["user"] as? [String: AnyObject])?["name"] as? String { 46 | // There's our username 47 | } 48 | 49 | ``` 50 | An unreadable mess--for something that should really be simple! 51 | 52 | With SwiftyJSON all you have to do is: 53 | 54 | ```swift 55 | 56 | let json = JSON(data: dataFromNetworking) 57 | if let userName = json[0]["user"]["name"].string { 58 | //Now you got your value 59 | } 60 | 61 | ``` 62 | 63 | And don't worry about the Optional Wrapping thing. It's done for you automatically. 64 | 65 | ```swift 66 | 67 | let json = JSON(data: dataFromNetworking) 68 | if let userName = json[999999]["wrong_key"]["wrong_name"].string { 69 | //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety 70 | } else { 71 | //Print the error 72 | print(json[999999]["wrong_key"]["wrong_name"]) 73 | } 74 | 75 | ``` 76 | 77 | ## Requirements 78 | 79 | Swift 3 80 | 81 | ## Integration 82 | 83 | #### Swift Package Manager 84 | 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: 85 | ```swift 86 | import PackageDescription 87 | 88 | let package = Package( 89 | name: "YOUR_PROJECT_NAME", 90 | targets: [], 91 | dependencies: [ 92 | .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", versions: "2.3.3" ..< Version.max) 93 | ] 94 | ) 95 | ``` 96 | ## Usage 97 | 98 | #### Initialization 99 | ```swift 100 | import SwiftyJSON 101 | ``` 102 | ```swift 103 | let json = JSON(data: dataFromNetworking) 104 | ``` 105 | ```swift 106 | let json = JSON(jsonObject) 107 | ``` 108 | ```swift 109 | if let dataFromString = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) { 110 | let json = JSON(data: dataFromString) 111 | } 112 | ``` 113 | 114 | #### Subscript 115 | ```swift 116 | //Getting a double from a JSON Array 117 | let name = json[0].double 118 | ``` 119 | ```swift 120 | //Getting a string from a JSON Dictionary 121 | let name = json["name"].stringValue 122 | ``` 123 | ```swift 124 | //Getting a string using a path to the element 125 | let path = [1,"list",2,"name"] 126 | let name = json[path].string 127 | //Just the same 128 | let name = json[1]["list"][2]["name"].string 129 | //Alternatively 130 | let name = json[1,"list",2,"name"].string 131 | ``` 132 | ```swift 133 | //With a hard way 134 | let name = json[].string 135 | ``` 136 | ```swift 137 | //With a custom way 138 | let keys:[SubscriptType] = [1,"list",2,"name"] 139 | let name = json[keys].string 140 | ``` 141 | #### Loop 142 | ```swift 143 | //If json is .Dictionary 144 | for (key,subJson):(String, JSON) in json { 145 | //Do something you want 146 | } 147 | ``` 148 | *The first element is always a String, even if the JSON is an Array* 149 | ```swift 150 | //If json is .Array 151 | //The `index` is 0.. = json["list"].arrayValue 250 | ``` 251 | ```swift 252 | //If not a Dictionary or nil, return [:] 253 | let user: Dictionary = json["user"].dictionaryValue 254 | ``` 255 | 256 | #### Setter 257 | ```swift 258 | json["name"] = JSON("new-name") 259 | json[0] = JSON(1) 260 | ``` 261 | ```swift 262 | json["id"].int = 1234567890 263 | json["coordinate"].double = 8766.766 264 | json["name"].string = "Jack" 265 | json.arrayObject = [1,2,3,4] 266 | json.dictionary = ["name":"Jack", "age":25] 267 | ``` 268 | 269 | #### Raw object 270 | ```swift 271 | let jsonObject: AnyObject = json.object 272 | ``` 273 | ```swift 274 | if let jsonObject: AnyObject = json.rawValue 275 | ``` 276 | ```swift 277 | //convert the JSON to raw NSData 278 | if let data = json.rawData() { 279 | //Do something you want 280 | } 281 | ``` 282 | ```swift 283 | //convert the JSON to a raw String 284 | if let string = json.rawString() { 285 | //Do something you want 286 | } 287 | ``` 288 | #### Existance 289 | ```swift 290 | //shows you whether value specified in JSON or not 291 | if json["name"].isExists() 292 | ``` 293 | 294 | #### Literal convertibles 295 | For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/) 296 | ```swift 297 | //StringLiteralConvertible 298 | let json: JSON = "I'm a json" 299 | ``` 300 | ```swift 301 | //IntegerLiteralConvertible 302 | let json: JSON = 12345 303 | ``` 304 | ```swift 305 | //BooleanLiteralConvertible 306 | let json: JSON = true 307 | ``` 308 | ```swift 309 | //FloatLiteralConvertible 310 | let json: JSON = 2.8765 311 | ``` 312 | ```swift 313 | //DictionaryLiteralConvertible 314 | let json: JSON = ["I":"am", "a":"json"] 315 | ``` 316 | ```swift 317 | //ArrayLiteralConvertible 318 | let json: JSON = ["I", "am", "a", "json"] 319 | ``` 320 | ```swift 321 | //NilLiteralConvertible 322 | let json: JSON = nil 323 | ``` 324 | ```swift 325 | //With subscript in array 326 | var json: JSON = [1,2,3] 327 | json[0] = 100 328 | json[1] = 200 329 | json[2] = 300 330 | json[999] = 300 //Don't worry, nothing will happen 331 | ``` 332 | ```swift 333 | //With subscript in dictionary 334 | var json: JSON = ["name": "Jack", "age": 25] 335 | json["name"] = "Mike" 336 | json["age"] = "25" //It's OK to set String 337 | json["address"] = "L.A." // Add the "address": "L.A." in json 338 | ``` 339 | ```swift 340 | //Array & Dictionary 341 | var json: JSON = ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]] 342 | json["list"][3]["what"] = "that" 343 | json["list",3,"what"] = "that" 344 | let path = ["list",3,"what"] 345 | json[path] = "that" 346 | ``` 347 | ## Work with Alamofire 348 | 349 | SwiftyJSON nicely wraps the result of the Alamofire JSON response handler: 350 | ```swift 351 | Alamofire.request(.GET, url).validate().responseJSON { response in 352 | switch response.result { 353 | case .Success: 354 | if let value = response.result.value { 355 | let json = JSON(value) 356 | print("JSON: \(json)") 357 | } 358 | case .Failure(let error): 359 | print(error) 360 | } 361 | } 362 | ``` 363 | -------------------------------------------------------------------------------- /Sources/SwiftyJSON/LclJSONSerialization.swift: -------------------------------------------------------------------------------- 1 | 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See http://swift.org/LICENSE.txt for license information 8 | // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 9 | // 10 | 11 | #if os(Linux) 12 | 13 | import CoreFoundation 14 | import Foundation 15 | 16 | import Glibc 17 | 18 | public class LclJSONSerialization { 19 | 20 | 21 | /* Determines whether the given object can be converted to JSON. 22 | Other rules may apply. Calling this method or attempting a conversion are the definitive ways 23 | to tell if a given object can be converted to JSON data. 24 | - parameter obj: The object to test. 25 | - returns: `true` if `obj` can be converted to JSON, otherwise `false`. 26 | */ 27 | open class func isValidJSONObject(_ obj: Any) -> Bool { 28 | // TODO: - revisit this once bridging story gets fully figured out 29 | func isValidJSONObjectInternal(_ obj: Any) -> Bool { 30 | // object is Swift.String, NSNull, Int, Bool, or UInt 31 | if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt { 32 | return true 33 | } 34 | 35 | // object is a Double and is not NaN or infinity 36 | if let number = obj as? Double { 37 | let invalid = number.isInfinite || number.isNaN 38 | return !invalid 39 | } 40 | // object is a Float and is not NaN or infinity 41 | if let number = obj as? Float { 42 | let invalid = number.isInfinite || number.isNaN 43 | return !invalid 44 | } 45 | 46 | // object is NSNumber and is not NaN or infinity 47 | if let number = obj as? NSNumber { 48 | let invalid = number.doubleValue.isInfinite || number.doubleValue.isNaN 49 | return !invalid 50 | } 51 | 52 | // object is Swift.Array 53 | if let array = obj as? [Any] { 54 | for element in array { 55 | guard isValidJSONObjectInternal(element) else { 56 | return false 57 | } 58 | } 59 | return true 60 | } 61 | 62 | // object is Swift.Dictionary 63 | if let dictionary = obj as? [String: Any] { 64 | for (_, value) in dictionary { 65 | guard isValidJSONObjectInternal(value) else { 66 | return false 67 | } 68 | } 69 | return true 70 | } 71 | 72 | // invalid object 73 | return false 74 | } 75 | 76 | // top level object must be an Swift.Array or Swift.Dictionary 77 | guard obj is [Any] || obj is [String: Any] else { 78 | return false 79 | } 80 | 81 | return isValidJSONObjectInternal(obj) 82 | } 83 | 84 | /* Generate JSON data from a Foundation object. If the object will not produce valid JSON then an exception will be thrown. Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable. If that option is not set, the most compact possible JSON will be generated. If an error occurs, the error parameter will be set and the return value will be nil. The resulting data is a encoded in UTF-8. 85 | */ 86 | internal class func _data(withJSONObject value: Any, options opt: JSONSerialization.WritingOptions, stream: Bool) throws -> Data { 87 | var jsonStr = String() 88 | jsonStr.reserveCapacity(5000) 89 | 90 | var writer = JSONWriter( 91 | pretty: opt.contains(.prettyPrinted), 92 | writer: { (str: String?) in 93 | if let str = str { 94 | jsonStr.append(str) 95 | } 96 | } 97 | ) 98 | 99 | if let container = value as? NSArray { 100 | try writer.serializeJSON(container._bridgeToSwift()) 101 | } else if let container = value as? NSDictionary { 102 | try writer.serializeJSON(container._bridgeToSwift()) 103 | } else if let container = value as? Array { 104 | try writer.serializeJSON(container) 105 | } else if let container = value as? Dictionary { 106 | try writer.serializeJSON(container) 107 | } else { 108 | if stream { 109 | throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: [ 110 | "NSDebugDescription" : "Top-level object was not NSArray or NSDictionary" 111 | ]) 112 | } else { 113 | fatalError("Top-level object was not NSArray or NSDictionary") // This is a fatal error in objective-c too (it is an NSInvalidArgumentException) 114 | } 115 | } 116 | 117 | let count = jsonStr.lengthOfBytes(using: .utf8) 118 | let bufferLength = count+1 // Allow space for null terminator 119 | var utf8: [CChar] = Array(repeating: 0, count: bufferLength) 120 | if !jsonStr.getCString(&utf8, maxLength: bufferLength, encoding: .utf8) { 121 | // throw something? 122 | } 123 | let rawBytes = UnsafeRawPointer(UnsafePointer(utf8)) 124 | let result = Data(bytes: rawBytes.bindMemory(to: UInt8.self, capacity: count), count: count) 125 | return result 126 | } 127 | open class func data(withJSONObject value: Any, options opt: JSONSerialization.WritingOptions = []) throws -> Data { 128 | return try _data(withJSONObject: value, options: opt, stream: false) 129 | } 130 | 131 | 132 | /* Write JSON data into a stream. The stream should be opened and configured. The return value is the number of bytes written to the stream, or 0 on error. All other behavior of this method is the same as the dataWithJSONObject:options:error: method. 133 | */ 134 | open class func writeJSONObject(_ obj: Any, toStream stream: OutputStream, options opt: JSONSerialization.WritingOptions) throws -> Int { 135 | let jsonData = try _data(withJSONObject: obj, options: opt, stream: true) 136 | let count = jsonData.count 137 | return jsonData.withUnsafeBytes { (bytePtr) -> Int in 138 | return stream.write(bytePtr, maxLength: count) 139 | } 140 | } 141 | } 142 | 143 | 144 | //MARK: - JSONSerializer 145 | private struct JSONWriter { 146 | 147 | var indent = 0 148 | let pretty: Bool 149 | let writer: (String?) -> Void 150 | 151 | init(pretty: Bool = false, writer: @escaping (String?) -> Void) { 152 | self.pretty = pretty 153 | self.writer = writer 154 | } 155 | 156 | mutating func serializeJSON(_ obj: Any) throws { 157 | 158 | if let str = obj as? String { 159 | try serializeString(str) 160 | } else if obj is Int || obj is Float || obj is Double || obj is UInt { 161 | writer(String(describing: obj)) 162 | } else if let boolValue = obj as? Bool { 163 | serializeBool(boolValue) 164 | } else if let num = obj as? NSNumber { 165 | try serializeNumber(num) 166 | } else if let array = obj as? Array { 167 | try serializeArray(array) 168 | } else if let dict = obj as? Dictionary { 169 | try serializeDictionary(dict) 170 | } else if let null = obj as? NSNull { 171 | try serializeNull(null) 172 | } else if let boolVal = obj as? Bool { 173 | try serializeNumber(NSNumber(value: boolVal)) 174 | } 175 | else { 176 | throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Invalid object cannot be serialized"]) 177 | } 178 | } 179 | 180 | func serializeString(_ str: String) throws { 181 | writer("\"") 182 | for scalar in str.unicodeScalars { 183 | switch scalar { 184 | case "\"": 185 | writer("\\\"") // U+0022 quotation mark 186 | case "\\": 187 | writer("\\\\") // U+005C reverse solidus 188 | // U+002F solidus not escaped 189 | case "\u{8}": 190 | writer("\\b") // U+0008 backspace 191 | case "\u{c}": 192 | writer("\\f") // U+000C form feed 193 | case "\n": 194 | writer("\\n") // U+000A line feed 195 | case "\r": 196 | writer("\\r") // U+000D carriage return 197 | case "\t": 198 | writer("\\t") // U+0009 tab 199 | case "\u{0}"..."\u{f}": 200 | writer("\\u000\(String(scalar.value, radix: 16))") // U+0000 to U+000F 201 | case "\u{10}"..."\u{1f}": 202 | writer("\\u00\(String(scalar.value, radix: 16))") // U+0010 to U+001F 203 | default: 204 | writer(String(scalar)) 205 | } 206 | } 207 | writer("\"") 208 | } 209 | 210 | func serializeBool(_ bool: Bool) { 211 | switch bool { 212 | case true: 213 | writer("true") 214 | case false: 215 | writer("false") 216 | } 217 | } 218 | 219 | mutating func serializeNumber(_ num: NSNumber) throws { 220 | if num.doubleValue.isInfinite || num.doubleValue.isNaN { 221 | throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Number cannot be infinity or NaN"]) 222 | } 223 | 224 | // Cannot detect type information (e.g. bool) as there is no objCType property on NSNumber in Swift 225 | // So, just print the number 226 | 227 | writer(JSON.stringFromNumber(num)) 228 | } 229 | 230 | mutating func serializeArray(_ array: [Any]) throws { 231 | writer("[") 232 | if pretty { 233 | writer("\n") 234 | incAndWriteIndent() 235 | } 236 | 237 | var first = true 238 | for elem in array { 239 | if first { 240 | first = false 241 | } else if pretty { 242 | writer(",\n") 243 | writeIndent() 244 | } else { 245 | writer(",") 246 | } 247 | try serializeJSON(elem) 248 | } 249 | if pretty { 250 | writer("\n") 251 | decAndWriteIndent() 252 | } 253 | writer("]") 254 | } 255 | 256 | mutating func serializeDictionary(_ dict: Dictionary) throws { 257 | writer("{") 258 | if pretty { 259 | writer("\n") 260 | incAndWriteIndent() 261 | } 262 | 263 | var first = true 264 | 265 | for (key, value) in dict { 266 | if first { 267 | first = false 268 | } else if pretty { 269 | writer(",\n") 270 | writeIndent() 271 | } else { 272 | writer(",") 273 | } 274 | 275 | if key is String { 276 | try serializeString(key as! String) 277 | } else { 278 | throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "NSDictionary key must be NSString"]) 279 | } 280 | pretty ? writer(": ") : writer(":") 281 | try serializeJSON(value) 282 | } 283 | if pretty { 284 | writer("\n") 285 | decAndWriteIndent() 286 | } 287 | writer("}") 288 | } 289 | 290 | func serializeNull(_ null: NSNull) throws { 291 | writer("null") 292 | } 293 | 294 | let indentAmount = 2 295 | 296 | mutating func incAndWriteIndent() { 297 | indent += indentAmount 298 | writeIndent() 299 | } 300 | 301 | mutating func decAndWriteIndent() { 302 | indent -= indentAmount 303 | writeIndent() 304 | } 305 | 306 | func writeIndent() { 307 | for _ in 0.. JSON { 91 | return string.data(using: String.Encoding.utf8).flatMap({JSON(data: $0)}) ?? JSON(NSNull()) 92 | } 93 | 94 | /** 95 | Creates a JSON using the object. 96 | 97 | - parameter object: The object must have the following properties: All objects are NSString/String, NSNumber/Int/Float/Double/Bool, NSArray/Array, NSDictionary/Dictionary, or NSNull; All dictionary keys are NSStrings/String; NSNumbers are not NaN or infinity. 98 | 99 | - returns: The created JSON 100 | */ 101 | public init(_ object: Any) { 102 | self.object = object 103 | } 104 | 105 | /** 106 | Creates a JSON from a [JSON] 107 | 108 | - parameter jsonArray: A Swift array of JSON objects 109 | 110 | - returns: The created JSON 111 | */ 112 | public init(_ jsonArray:[JSON]) { 113 | self.init(jsonArray.map { $0.object } as Any) 114 | } 115 | 116 | /** 117 | Creates a JSON from a [String: JSON] 118 | 119 | - parameter jsonDictionary: A Swift dictionary of JSON objects 120 | 121 | - returns: The created JSON 122 | */ 123 | public init(_ jsonDictionary:[String: JSON]) { 124 | var dictionary = [String: Any](minimumCapacity: jsonDictionary.count) 125 | 126 | for (key, json) in jsonDictionary { 127 | dictionary[key] = json.object 128 | } 129 | self.init(dictionary as Any) 130 | } 131 | 132 | /// Private object 133 | var rawString: String = "" 134 | var rawNumber: NSNumber = 0 135 | var rawNull: NSNull = NSNull() 136 | var rawArray: [Any] = [] 137 | var rawDictionary: [String : Any] = [:] 138 | var rawBool: Bool = false 139 | /// Private type 140 | var _type: Type = .null 141 | /// prviate error 142 | var _error: NSError? = nil 143 | 144 | 145 | /// Object in JSON 146 | public var object: Any { 147 | get { 148 | switch self.type { 149 | case .array: 150 | return self.rawArray 151 | case .dictionary: 152 | return self.rawDictionary 153 | case .string: 154 | return self.rawString 155 | case .number: 156 | return self.rawNumber 157 | case .bool: 158 | return self.rawBool 159 | default: 160 | return self.rawNull 161 | } 162 | } 163 | 164 | set { 165 | _error = nil 166 | 167 | #if os(Linux) 168 | let (type, value) = self.setObjectHelper(newValue) 169 | 170 | _type = type 171 | switch (type) { 172 | case .array: 173 | self.rawArray = value as! [Any] 174 | case .bool: 175 | self.rawBool = value as! Bool 176 | if let number = newValue as? NSNumber { 177 | self.rawNumber = number 178 | } 179 | else { 180 | self.rawNumber = self.rawBool ? NSNumber(value: 1) : NSNumber(value: 0) 181 | } 182 | case .dictionary: 183 | self.rawDictionary = value as! [String:Any] 184 | case .null: 185 | break 186 | case .number: 187 | self.rawNumber = value as! NSNumber 188 | case .string: 189 | self.rawString = value as! String 190 | case .unknown: 191 | _error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"]) 192 | print("==> error=\(String(describing: _error)). type=\(Swift.type(of: newValue))") 193 | } 194 | #else 195 | if Swift.type(of: newValue) == Bool.self { 196 | _type = .bool 197 | self.rawBool = newValue as! Bool 198 | } 199 | else { 200 | switch newValue { 201 | case let number as NSNumber: 202 | if number.isBool { 203 | _type = .bool 204 | self.rawBool = number.boolValue 205 | } else { 206 | _type = .number 207 | self.rawNumber = number 208 | } 209 | case let string as String: 210 | _type = .string 211 | self.rawString = string 212 | case _ as NSNull: 213 | _type = .null 214 | case let array as [Any]: 215 | _type = .array 216 | self.rawArray = array 217 | case let dictionary as [String : Any]: 218 | _type = .dictionary 219 | self.rawDictionary = dictionary 220 | default: 221 | _type = .unknown 222 | 223 | #if swift(>=3.2) 224 | _error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"]) 225 | #else 226 | _error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey as NSObject: "It is a unsupported type"]) 227 | #endif 228 | } 229 | } 230 | 231 | #endif 232 | } 233 | } 234 | 235 | #if os(Linux) 236 | private func setObjectHelper(_ newValue: Any) -> (Type, Any) { 237 | var type: Type 238 | var value: Any 239 | 240 | if let number = newValue as? Int { 241 | type = .number 242 | value = NSNumber(value: number) 243 | } else if let number = newValue as? Double { 244 | type = .number 245 | value = NSNumber(value: number) 246 | } else if let bool = newValue as? Bool { 247 | type = .bool 248 | value = bool 249 | } else if let number = newValue as? NSNumber { 250 | if number.isBool { 251 | type = .bool 252 | value = number.boolValue 253 | } else { 254 | type = .number 255 | value = number 256 | } 257 | } else if let string = newValue as? String { 258 | type = .string 259 | value = string 260 | } else if let string = newValue as? NSString { 261 | type = .string 262 | value = string._bridgeToSwift() 263 | } else if newValue is NSNull { 264 | type = .null 265 | value = "" 266 | } else if let array = newValue as? NSArray { 267 | type = .array 268 | value = array._bridgeToSwift() 269 | } else if let array = newValue as? Array { 270 | type = .array 271 | value = array 272 | } else if let dictionary = newValue as? NSDictionary { 273 | type = .dictionary 274 | value = dictionary._bridgeToSwift() 275 | } else if let dictionary = newValue as? Dictionary { 276 | type = .dictionary 277 | value = dictionary 278 | } else { 279 | type = .unknown 280 | value = "" 281 | } 282 | return (type, value) 283 | } 284 | 285 | #endif 286 | 287 | /// json type 288 | public var type: Type { get { return _type } } 289 | 290 | /// Error in JSON 291 | public var error: NSError? { get { return self._error } } 292 | 293 | /// The static null json 294 | @available(*, unavailable, renamed:"null") 295 | public static var nullJSON: JSON { get { return null } } 296 | public static var null: JSON { get { return JSON(NSNull() as Any) } } 297 | #if os(Linux) 298 | internal static func stringFromNumber(_ number: NSNumber) -> String { 299 | let type = CFNumberGetType(unsafeBitCast(number, to: CFNumber.self)) 300 | switch(type) { 301 | case kCFNumberFloat32Type: 302 | return String(number.floatValue) 303 | case kCFNumberFloat64Type: 304 | return String(number.doubleValue) 305 | default: 306 | return String(number.int64Value) 307 | } 308 | } 309 | #endif 310 | } 311 | 312 | // MARK: - CollectionType, SequenceType 313 | extension JSON : Collection, Sequence { 314 | 315 | public typealias Generator = JSONGenerator 316 | 317 | public typealias Index = JSONIndex 318 | 319 | public var startIndex: JSON.Index { 320 | switch self.type { 321 | case .array: 322 | return JSONIndex(arrayIndex: self.rawArray.startIndex) 323 | case .dictionary: 324 | return JSONIndex(dictionaryIndex: self.rawDictionary.startIndex) 325 | default: 326 | return JSONIndex() 327 | } 328 | } 329 | 330 | public var endIndex: JSON.Index { 331 | switch self.type { 332 | case .array: 333 | return JSONIndex(arrayIndex: self.rawArray.endIndex) 334 | case .dictionary: 335 | return JSONIndex(dictionaryIndex: self.rawDictionary.endIndex) 336 | default: 337 | return JSONIndex() 338 | } 339 | } 340 | 341 | public func index(after i: JSON.Index) -> JSON.Index { 342 | switch self.type { 343 | case .array: 344 | return JSONIndex(arrayIndex: self.rawArray.index(after: i.arrayIndex!)) 345 | case .dictionary: 346 | return JSONIndex(dictionaryIndex: self.rawDictionary.index(after: i.dictionaryIndex!)) 347 | default: 348 | return JSONIndex() 349 | } 350 | } 351 | 352 | public subscript (position: JSON.Index) -> Generator.Element { 353 | switch self.type { 354 | case .array: 355 | return (String(describing: position.arrayIndex), JSON(self.rawArray[position.arrayIndex!])) 356 | case .dictionary: 357 | let (key, value) = self.rawDictionary[position.dictionaryIndex!] 358 | return (key, JSON(value)) 359 | default: 360 | return ("", JSON.null) 361 | } 362 | } 363 | 364 | /// If `type` is `.Array` or `.Dictionary`, return `array.isEmpty` or `dictonary.isEmpty` otherwise return `true`. 365 | public var isEmpty: Bool { 366 | get { 367 | switch self.type { 368 | case .array: 369 | return self.rawArray.isEmpty 370 | case .dictionary: 371 | return self.rawDictionary.isEmpty 372 | default: 373 | return true 374 | } 375 | } 376 | } 377 | 378 | /// If `type` is `.Array` or `.Dictionary`, return `array.count` or `dictonary.count` otherwise return `0`. 379 | public var count: Int { 380 | switch self.type { 381 | case .array: 382 | return self.rawArray.count 383 | case .dictionary: 384 | return self.rawDictionary.count 385 | default: 386 | return 0 387 | } 388 | } 389 | 390 | public func underestimateCount() -> Int { 391 | switch self.type { 392 | case .array: 393 | return self.rawArray.underestimatedCount 394 | case .dictionary: 395 | return self.rawDictionary.underestimatedCount 396 | default: 397 | return 0 398 | } 399 | } 400 | 401 | /** 402 | If `type` is `.Array` or `.Dictionary`, return a generator over the elements like `Array` or `Dictionary`, otherwise return a generator over empty. 403 | 404 | - returns: Return a *generator* over the elements of JSON. 405 | */ 406 | public func generate() -> Generator { 407 | return JSON.Generator(self) 408 | } 409 | } 410 | 411 | public struct JSONIndex: Equatable, Comparable { 412 | let arrayIndex: Array.Index? 413 | let dictionaryIndex: DictionaryIndex? 414 | let type: Type 415 | 416 | init(){ 417 | self.arrayIndex = nil 418 | self.dictionaryIndex = nil 419 | self.type = .unknown 420 | } 421 | 422 | init(arrayIndex: Array.Index) { 423 | self.arrayIndex = arrayIndex 424 | self.dictionaryIndex = nil 425 | self.type = .array 426 | } 427 | 428 | init(dictionaryIndex: DictionaryIndex) { 429 | self.arrayIndex = nil 430 | self.dictionaryIndex = dictionaryIndex 431 | self.type = .dictionary 432 | } 433 | } 434 | 435 | public func ==(lhs: JSONIndex, rhs: JSONIndex) -> Bool { 436 | switch (lhs.type, rhs.type) { 437 | case (.array, .array): 438 | return lhs.arrayIndex == rhs.arrayIndex 439 | case (.dictionary, .dictionary): 440 | return lhs.dictionaryIndex == rhs.dictionaryIndex 441 | default: 442 | return false 443 | } 444 | } 445 | 446 | public func <(lhs: JSONIndex, rhs: JSONIndex) -> Bool { 447 | switch (lhs.type, rhs.type) { 448 | case (.array, .array): 449 | guard let lhsArrayIndex = lhs.arrayIndex, 450 | let rhsArrayIndex = rhs.arrayIndex else { return false } 451 | return lhsArrayIndex < rhsArrayIndex 452 | case (.dictionary, .dictionary): 453 | guard let lhsDictionaryIndex = lhs.dictionaryIndex, 454 | let rhsDictionaryIndex = rhs.dictionaryIndex else { return false } 455 | return lhsDictionaryIndex < rhsDictionaryIndex 456 | default: 457 | return false 458 | } 459 | } 460 | 461 | public func <=(lhs: JSONIndex, rhs: JSONIndex) -> Bool { 462 | switch (lhs.type, rhs.type) { 463 | case (.array, .array): 464 | guard let lhsArrayIndex = lhs.arrayIndex, 465 | let rhsArrayIndex = rhs.arrayIndex else { return false } 466 | return lhsArrayIndex < rhsArrayIndex 467 | case (.dictionary, .dictionary): 468 | guard let lhsDictionaryIndex = lhs.dictionaryIndex, 469 | let rhsDictionaryIndex = rhs.dictionaryIndex else { return false } 470 | return lhsDictionaryIndex < rhsDictionaryIndex 471 | default: 472 | return false 473 | } 474 | } 475 | 476 | public func >=(lhs: JSONIndex, rhs: JSONIndex) -> Bool { 477 | switch (lhs.type, rhs.type) { 478 | case (.array, .array): 479 | guard let lhsArrayIndex = lhs.arrayIndex, 480 | let rhsArrayIndex = rhs.arrayIndex else { return false } 481 | return lhsArrayIndex < rhsArrayIndex 482 | case (.dictionary, .dictionary): 483 | guard let lhsDictionaryIndex = lhs.dictionaryIndex, 484 | let rhsDictionaryIndex = rhs.dictionaryIndex else { return false } 485 | return lhsDictionaryIndex < rhsDictionaryIndex 486 | default: 487 | return false 488 | } 489 | } 490 | 491 | public func >(lhs: JSONIndex, rhs: JSONIndex) -> Bool { 492 | switch (lhs.type, rhs.type) { 493 | case (.array, .array): 494 | guard let lhsArrayIndex = lhs.arrayIndex, 495 | let rhsArrayIndex = rhs.arrayIndex else { return false } 496 | return lhsArrayIndex < rhsArrayIndex 497 | case (.dictionary, .dictionary): 498 | guard let lhsDictionaryIndex = lhs.dictionaryIndex, 499 | let rhsDictionaryIndex = rhs.dictionaryIndex else { return false } 500 | return lhsDictionaryIndex < rhsDictionaryIndex 501 | default: 502 | return false 503 | } 504 | } 505 | 506 | public struct JSONGenerator : IteratorProtocol { 507 | 508 | public typealias Element = (String, JSON) 509 | 510 | private let type: Type 511 | private var dictionayGenerate: DictionaryIterator? 512 | private var arrayGenerate: IndexingIterator<[Any]>? 513 | private var arrayIndex: Int = 0 514 | 515 | init(_ json: JSON) { 516 | self.type = json.type 517 | if type == .array { 518 | self.arrayGenerate = json.rawArray.makeIterator() 519 | }else { 520 | self.dictionayGenerate = json.rawDictionary.makeIterator() 521 | } 522 | } 523 | 524 | public mutating func next() -> JSONGenerator.Element? { 525 | switch self.type { 526 | case .array: 527 | if let o = self.arrayGenerate?.next() { 528 | let i = self.arrayIndex 529 | self.arrayIndex += 1 530 | return (String(i), JSON(o)) 531 | } else { 532 | return nil 533 | } 534 | case .dictionary: 535 | guard let (k, v): (String, Any) = self.dictionayGenerate?.next() else { 536 | return nil 537 | } 538 | return (k, JSON(v)) 539 | 540 | default: 541 | return nil 542 | } 543 | } 544 | } 545 | 546 | // MARK: - Subscript 547 | 548 | /** 549 | * To mark both String and Int can be used in subscript. 550 | */ 551 | public enum JSONKey { 552 | case index(Int) 553 | case key(String) 554 | } 555 | 556 | public protocol JSONSubscriptType { 557 | var jsonKey:JSONKey { get } 558 | } 559 | 560 | extension Int: JSONSubscriptType { 561 | public var jsonKey:JSONKey { 562 | return JSONKey.index(self) 563 | } 564 | } 565 | 566 | extension String: JSONSubscriptType { 567 | public var jsonKey:JSONKey { 568 | return JSONKey.key(self) 569 | } 570 | } 571 | 572 | extension JSON { 573 | 574 | /// If `type` is `.Array`, return json whose object is `array[index]`, otherwise return null json with error. 575 | private subscript(index index: Int) -> JSON { 576 | get { 577 | if self.type != .array { 578 | var r = JSON.null 579 | r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] failure, It is not an array" as Any]) 580 | return r 581 | } else if index >= 0 && index < self.rawArray.count { 582 | return JSON(self.rawArray[index]) 583 | } else { 584 | var r = JSON.null 585 | #if os(Linux) 586 | r._error = NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds, userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] is out of bounds" as Any]) 587 | #elseif swift(>=3.2) 588 | r._error = NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds, userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] is out of bounds" as AnyObject]) 589 | #else 590 | r._error = NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds, userInfo: [NSLocalizedDescriptionKey as AnyObject as! NSObject: "Array[\(index)] is out of bounds" as AnyObject]) 591 | #endif 592 | return r 593 | } 594 | } 595 | set { 596 | if self.type == .array { 597 | if self.rawArray.count > index && newValue.error == nil { 598 | self.rawArray[index] = newValue.object 599 | } 600 | } 601 | } 602 | } 603 | 604 | /// If `type` is `.Dictionary`, return json whose object is `dictionary[key]` , otherwise return null json with error. 605 | private subscript(key key: String) -> JSON { 606 | get { 607 | var r = JSON.null 608 | if self.type == .dictionary { 609 | if let o = self.rawDictionary[key] { 610 | r = JSON(o) 611 | } else { 612 | #if os(Linux) 613 | r._error = NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] does not exist" as Any]) 614 | #elseif swift(>=3.2) 615 | r._error = NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] does not exist" as AnyObject]) 616 | #else 617 | r._error = NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey as NSObject: "Dictionary[\"\(key)\"] does not exist" as AnyObject]) 618 | #endif 619 | } 620 | } else { 621 | #if os(Linux) 622 | r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] failure, It is not an dictionary" as Any]) 623 | #elseif swift(>=3.2) 624 | r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] failure, It is not an dictionary" as AnyObject]) 625 | #else 626 | r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey as NSObject: "Dictionary[\"\(key)\"] failure, It is not an dictionary" as AnyObject]) 627 | #endif 628 | } 629 | return r 630 | } 631 | set { 632 | if self.type == .dictionary && newValue.error == nil { 633 | self.rawDictionary[key] = newValue.object 634 | } 635 | } 636 | } 637 | 638 | /// If `sub` is `Int`, return `subscript(index:)`; If `sub` is `String`, return `subscript(key:)`. 639 | private subscript(sub sub: JSONSubscriptType) -> JSON { 640 | get { 641 | switch sub.jsonKey { 642 | case .index(let index): return self[index: index] 643 | case .key(let key): return self[key: key] 644 | } 645 | } 646 | set { 647 | switch sub.jsonKey { 648 | case .index(let index): self[index: index] = newValue 649 | case .key(let key): self[key: key] = newValue 650 | } 651 | } 652 | } 653 | 654 | /** 655 | Find a json in the complex data structuresby using the Int/String's array. 656 | 657 | - parameter path: The target json's path. Example: 658 | 659 | let json = JSON[data] 660 | let path = [9,"list","person","name"] 661 | let name = json[path] 662 | 663 | The same as: let name = json[9]["list"]["person"]["name"] 664 | 665 | - returns: Return a json found by the path or a null json with error 666 | */ 667 | public subscript(path: [JSONSubscriptType]) -> JSON { 668 | get { 669 | return path.reduce(self) { $0[sub: $1] } 670 | } 671 | set { 672 | switch path.count { 673 | case 0: 674 | self.object = newValue.object 675 | case 1: 676 | self[sub:path[0]].object = newValue.object 677 | default: 678 | var aPath = path; aPath.remove(at: 0) 679 | var nextJSON = self[sub: path[0]] 680 | nextJSON[aPath] = newValue 681 | self[sub: path[0]] = nextJSON 682 | } 683 | } 684 | } 685 | 686 | /** 687 | Find a json in the complex data structures by using the Int/String's array. 688 | 689 | - parameter path: The target json's path. Example: 690 | 691 | let name = json[9,"list","person","name"] 692 | 693 | The same as: let name = json[9]["list"]["person"]["name"] 694 | 695 | - returns: Return a json found by the path or a null json with error 696 | */ 697 | public subscript(path: JSONSubscriptType...) -> JSON { 698 | get { 699 | return self[path] 700 | } 701 | set { 702 | self[path] = newValue 703 | } 704 | } 705 | } 706 | 707 | // MARK: - LiteralConvertible 708 | 709 | //TODO: Remove this after we remove support for Swift 3.0.2 710 | #if swift(>=3.1) 711 | typealias ExpressibleByStringLiteralType = ExpressibleByStringLiteral 712 | typealias ExpressibleByIntegerLiteralType = ExpressibleByIntegerLiteral 713 | typealias ExpressibleByBooleanLiteralType = ExpressibleByBooleanLiteral 714 | typealias ExpressibleByFloatLiteralType = ExpressibleByFloatLiteral 715 | typealias ExpressibleByDictionaryLiteralType = ExpressibleByDictionaryLiteral 716 | typealias ExpressibleByArrayLiteralType = ExpressibleByArrayLiteral 717 | typealias ExpressibleByNilLiteralType = ExpressibleByNilLiteral 718 | #else 719 | typealias ExpressibleByStringLiteralType = Swift.StringLiteralConvertible 720 | typealias ExpressibleByIntegerLiteralType = Swift.IntegerLiteralConvertible 721 | typealias ExpressibleByBooleanLiteralType = Swift.BooleanLiteralConvertible 722 | typealias ExpressibleByFloatLiteralType = Swift.FloatLiteralConvertible 723 | typealias ExpressibleByDictionaryLiteralType = Swift.DictionaryLiteralConvertible 724 | typealias ExpressibleByArrayLiteralType = Swift.ArrayLiteralConvertible 725 | typealias ExpressibleByNilLiteralType = Swift.NilLiteralConvertible 726 | #endif 727 | 728 | extension JSON: ExpressibleByStringLiteralType { 729 | 730 | public init(stringLiteral value: StringLiteralType) { 731 | self.init(value as Any) 732 | } 733 | 734 | public init(extendedGraphemeClusterLiteral value: StringLiteralType) { 735 | self.init(value as Any) 736 | } 737 | 738 | public init(unicodeScalarLiteral value: StringLiteralType) { 739 | self.init(value as Any) 740 | } 741 | } 742 | 743 | extension JSON: ExpressibleByIntegerLiteralType { 744 | 745 | public init(integerLiteral value: IntegerLiteralType) { 746 | self.init(value as Any) 747 | } 748 | } 749 | 750 | extension JSON: ExpressibleByBooleanLiteralType { 751 | 752 | public init(booleanLiteral value: BooleanLiteralType) { 753 | self.init(value as Any) 754 | } 755 | } 756 | 757 | extension JSON: ExpressibleByFloatLiteralType { 758 | 759 | public init(floatLiteral value: FloatLiteralType) { 760 | self.init(value as Any) 761 | } 762 | } 763 | 764 | extension JSON: ExpressibleByDictionaryLiteralType { 765 | 766 | public init(dictionaryLiteral elements: (String, Any)...) { 767 | self.init(elements.reduce([String : Any](minimumCapacity: elements.count)){(dictionary: [String : Any], element:(String, Any)) -> [String : Any] in 768 | var d = dictionary 769 | d[element.0] = element.1 770 | return d 771 | } as Any) 772 | } 773 | } 774 | 775 | extension JSON: ExpressibleByArrayLiteralType { 776 | 777 | public init(arrayLiteral elements: Any...) { 778 | self.init(elements as Any) 779 | } 780 | } 781 | 782 | extension JSON: ExpressibleByNilLiteralType { 783 | 784 | public init(nilLiteral: ()) { 785 | self.init(NSNull() as Any) 786 | } 787 | } 788 | 789 | // MARK: - Raw 790 | 791 | extension JSON: Swift.RawRepresentable { 792 | 793 | public init?(rawValue: Any) { 794 | if JSON(rawValue).type == .unknown { 795 | return nil 796 | } else { 797 | self.init(rawValue) 798 | } 799 | } 800 | 801 | public var rawValue: Any { 802 | return self.object 803 | } 804 | #if os(Linux) 805 | public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data { 806 | guard LclJSONSerialization.isValidJSONObject(self.object) else { 807 | throw SwiftyJSONError.errorInvalidJSON("JSON is invalid") 808 | } 809 | 810 | return try LclJSONSerialization.data(withJSONObject: self.object, options: opt) 811 | } 812 | #else 813 | public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data { 814 | guard JSONSerialization.isValidJSONObject(self.object) else { 815 | throw SwiftyJSONError.errorInvalidJSON("JSON is invalid") 816 | } 817 | 818 | return try JSONSerialization.data(withJSONObject: self.object, options: opt) 819 | } 820 | #endif 821 | 822 | #if os(Linux) 823 | public func rawString(encoding: String.Encoding = String.Encoding.utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? { 824 | switch self.type { 825 | case .array, .dictionary: 826 | do { 827 | let data = try self.rawData(options: opt) 828 | return String(data: data, encoding: encoding) 829 | } catch _ { 830 | return nil 831 | } 832 | case .string: 833 | return self.rawString 834 | case .number: 835 | return JSON.stringFromNumber(self.rawNumber) 836 | case .bool: 837 | return self.rawBool.description 838 | case .null: 839 | return "null" 840 | default: 841 | return nil 842 | } 843 | } 844 | #else 845 | public func rawString(encoding: String.Encoding = String.Encoding.utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? { 846 | switch self.type { 847 | case .array, .dictionary: 848 | do { 849 | let data = try self.rawData(options: opt) 850 | return String(data: data, encoding: encoding) 851 | } catch _ { 852 | return nil 853 | } 854 | case .string: 855 | return self.rawString 856 | case .number: 857 | return self.rawNumber.stringValue 858 | case .bool: 859 | return self.rawBool.description 860 | case .null: 861 | return "null" 862 | default: 863 | return nil 864 | } 865 | } 866 | #endif 867 | } 868 | 869 | // MARK: - Printable, DebugPrintable 870 | 871 | extension JSON { 872 | 873 | public var description: String { 874 | let prettyString = self.rawString(options:.prettyPrinted) 875 | if let string = prettyString { 876 | return string 877 | } else { 878 | return "unknown" 879 | } 880 | } 881 | 882 | public var debugDescription: String { 883 | return description 884 | } 885 | } 886 | 887 | // MARK: - Array 888 | 889 | extension JSON { 890 | 891 | //Optional [JSON] 892 | public var array: [JSON]? { 893 | get { 894 | if self.type == .array { 895 | return self.rawArray.map{ JSON($0) } 896 | } else { 897 | return nil 898 | } 899 | } 900 | } 901 | 902 | //Non-optional [JSON] 903 | public var arrayValue: [JSON] { 904 | get { 905 | return self.array ?? [] 906 | } 907 | } 908 | 909 | //Optional [AnyType] 910 | public var arrayObject: [Any]? { 911 | get { 912 | switch self.type { 913 | case .array: 914 | return self.rawArray 915 | default: 916 | return nil 917 | } 918 | } 919 | set { 920 | if let array = newValue { 921 | self.object = array as Any 922 | } else { 923 | self.object = NSNull() 924 | } 925 | } 926 | } 927 | } 928 | 929 | // MARK: - Dictionary 930 | 931 | extension JSON { 932 | 933 | //Optional [String : JSON] 934 | public var dictionary: [String : JSON]? { 935 | if self.type == .dictionary { 936 | return self.rawDictionary.reduce([String : JSON]()) { (dictionary: [String : JSON], element: (String, Any)) -> [String : JSON] in 937 | var d = dictionary 938 | d[element.0] = JSON(element.1) 939 | return d 940 | } 941 | } else { 942 | return nil 943 | } 944 | } 945 | 946 | //Non-optional [String : JSON] 947 | public var dictionaryValue: [String : JSON] { 948 | return self.dictionary ?? [:] 949 | } 950 | 951 | //Optional [String : AnyType] 952 | public var dictionaryObject: [String : Any]? { 953 | get { 954 | switch self.type { 955 | case .dictionary: 956 | return self.rawDictionary 957 | default: 958 | return nil 959 | } 960 | } 961 | set { 962 | if let v = newValue { 963 | self.object = v as Any 964 | } else { 965 | self.object = NSNull() 966 | } 967 | } 968 | } 969 | } 970 | 971 | // MARK: - Bool 972 | 973 | extension JSON { 974 | 975 | //Optional bool 976 | public var bool: Bool? { 977 | get { 978 | switch self.type { 979 | case .bool: 980 | return self.rawBool 981 | default: 982 | return nil 983 | } 984 | } 985 | set { 986 | if let newValue = newValue { 987 | self.object = newValue as Bool 988 | } else { 989 | self.object = NSNull() 990 | } 991 | } 992 | } 993 | 994 | //Non-optional bool 995 | public var boolValue: Bool { 996 | get { 997 | switch self.type { 998 | case .bool: 999 | return self.rawBool 1000 | case .number: 1001 | return self.rawNumber.boolValue 1002 | case .string: 1003 | return self.rawString.caseInsensitiveCompare("true") == .orderedSame 1004 | default: 1005 | return false 1006 | } 1007 | } 1008 | set { 1009 | self.object = newValue 1010 | } 1011 | } 1012 | } 1013 | 1014 | // MARK: - String 1015 | 1016 | extension JSON { 1017 | 1018 | //Optional string 1019 | public var string: String? { 1020 | get { 1021 | switch self.type { 1022 | case .string: 1023 | return self.object as? String 1024 | default: 1025 | return nil 1026 | } 1027 | } 1028 | set { 1029 | if let newValue = newValue { 1030 | self.object = NSString(string:newValue) 1031 | } else { 1032 | self.object = NSNull() 1033 | } 1034 | } 1035 | } 1036 | 1037 | //Non-optional string 1038 | public var stringValue: String { 1039 | get { 1040 | 1041 | #if os(Linux) 1042 | switch self.type { 1043 | case .string: 1044 | return self.object as? String ?? "" 1045 | case .number: 1046 | return JSON.stringFromNumber(self.object as! NSNumber) 1047 | case .bool: 1048 | return String(self.object as! Bool) 1049 | default: 1050 | return "" 1051 | } 1052 | #else 1053 | switch self.type { 1054 | case .string: 1055 | return self.object as? String ?? "" 1056 | case .number: 1057 | return self.rawNumber.stringValue 1058 | case .bool: 1059 | return (self.object as? Bool).map { String($0) } ?? "" 1060 | default: 1061 | return "" 1062 | } 1063 | #endif 1064 | } 1065 | set { 1066 | self.object = NSString(string:newValue) 1067 | } 1068 | } 1069 | } 1070 | 1071 | // MARK: - Number 1072 | extension JSON { 1073 | 1074 | //Optional number 1075 | public var number: NSNumber? { 1076 | get { 1077 | switch self.type { 1078 | case .number: 1079 | return self.rawNumber 1080 | case .bool: 1081 | return NSNumber(value: self.rawBool ? 1 : 0) 1082 | default: 1083 | return nil 1084 | } 1085 | } 1086 | set { 1087 | self.object = newValue ?? NSNull() 1088 | } 1089 | } 1090 | 1091 | //Non-optional number 1092 | public var numberValue: NSNumber { 1093 | get { 1094 | switch self.type { 1095 | case .string: 1096 | #if os(Linux) 1097 | if let decimal = Double(self.object as! String) { 1098 | return NSNumber(value: decimal) 1099 | } 1100 | else { // indicates parse error 1101 | return NSNumber(value: 0.0) 1102 | } 1103 | #else 1104 | let decimal = NSDecimalNumber(string: self.object as? String) 1105 | if decimal == NSDecimalNumber.notANumber { // indicates parse error 1106 | return NSDecimalNumber.zero 1107 | } 1108 | return decimal 1109 | #endif 1110 | case .number: 1111 | return self.object as? NSNumber ?? NSNumber(value: 0) 1112 | case .bool: 1113 | return NSNumber(value: self.rawBool ? 1 : 0) 1114 | default: 1115 | return NSNumber(value: 0.0) 1116 | } 1117 | } 1118 | set { 1119 | self.object = newValue 1120 | } 1121 | } 1122 | } 1123 | 1124 | //MARK: - Null 1125 | extension JSON { 1126 | 1127 | public var null: NSNull? { 1128 | get { 1129 | switch self.type { 1130 | case .null: 1131 | return self.rawNull 1132 | default: 1133 | return nil 1134 | } 1135 | } 1136 | set { 1137 | self.object = NSNull() 1138 | } 1139 | } 1140 | public func exists() -> Bool{ 1141 | if let errorValue = error, errorValue.code == ErrorNotExist{ 1142 | return false 1143 | } 1144 | return true 1145 | } 1146 | } 1147 | 1148 | //MARK: - URL 1149 | extension JSON { 1150 | 1151 | //Optional URL 1152 | public var URL: NSURL? { 1153 | get { 1154 | switch self.type { 1155 | case .string: 1156 | guard let encodedString_ = self.rawString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { 1157 | return nil 1158 | } 1159 | return NSURL(string: encodedString_) 1160 | 1161 | default: 1162 | return nil 1163 | } 1164 | } 1165 | set { 1166 | #if os(Linux) 1167 | self.object = newValue?.absoluteString._bridgeToObjectiveC() as Any 1168 | #else 1169 | self.object = newValue?.absoluteString as Any 1170 | #endif 1171 | } 1172 | } 1173 | } 1174 | 1175 | // MARK: - Int, Double, Float, Int8, Int16, Int32, Int64 1176 | 1177 | extension JSON { 1178 | 1179 | public var double: Double? { 1180 | get { 1181 | return self.number?.doubleValue 1182 | } 1183 | set { 1184 | if let newValue = newValue { 1185 | self.object = NSNumber(value: newValue) 1186 | } else { 1187 | self.object = NSNull() 1188 | } 1189 | } 1190 | } 1191 | 1192 | public var doubleValue: Double { 1193 | get { 1194 | return self.numberValue.doubleValue 1195 | } 1196 | set { 1197 | self.object = NSNumber(value: newValue) 1198 | } 1199 | } 1200 | 1201 | public var float: Float? { 1202 | get { 1203 | return self.number?.floatValue 1204 | } 1205 | set { 1206 | if let newValue = newValue { 1207 | self.object = NSNumber(value: newValue) 1208 | } else { 1209 | self.object = NSNull() 1210 | } 1211 | } 1212 | } 1213 | 1214 | public var floatValue: Float { 1215 | get { 1216 | return self.numberValue.floatValue 1217 | } 1218 | set { 1219 | self.object = NSNumber(value: newValue) 1220 | } 1221 | } 1222 | 1223 | public var int: Int? { 1224 | get { 1225 | return self.number?.intValue 1226 | } 1227 | set { 1228 | if let newValue = newValue { 1229 | self.object = NSNumber(value: newValue) 1230 | } else { 1231 | self.object = NSNull() 1232 | } 1233 | } 1234 | } 1235 | 1236 | public var intValue: Int { 1237 | get { 1238 | return self.numberValue.intValue 1239 | } 1240 | set { 1241 | self.object = NSNumber(value: newValue) 1242 | } 1243 | } 1244 | 1245 | public var uInt: UInt? { 1246 | get { 1247 | return self.number?.uintValue 1248 | } 1249 | set { 1250 | if let newValue = newValue { 1251 | self.object = NSNumber(value: newValue) 1252 | } else { 1253 | self.object = NSNull() 1254 | } 1255 | } 1256 | } 1257 | 1258 | public var uIntValue: UInt { 1259 | get { 1260 | return self.numberValue.uintValue 1261 | } 1262 | set { 1263 | self.object = NSNumber(value: newValue) 1264 | } 1265 | } 1266 | 1267 | public var int8: Int8? { 1268 | get { 1269 | return self.number?.int8Value 1270 | } 1271 | set { 1272 | if let newValue = newValue { 1273 | self.object = NSNumber(value: newValue) 1274 | } else { 1275 | self.object = NSNull() 1276 | } 1277 | } 1278 | } 1279 | 1280 | public var int8Value: Int8 { 1281 | get { 1282 | return self.numberValue.int8Value 1283 | } 1284 | set { 1285 | self.object = NSNumber(value: newValue) 1286 | } 1287 | } 1288 | 1289 | public var uInt8: UInt8? { 1290 | get { 1291 | return self.number?.uint8Value 1292 | } 1293 | set { 1294 | if let newValue = newValue { 1295 | self.object = NSNumber(value: newValue) 1296 | } else { 1297 | self.object = NSNull() 1298 | } 1299 | } 1300 | } 1301 | 1302 | public var uInt8Value: UInt8 { 1303 | get { 1304 | return self.numberValue.uint8Value 1305 | } 1306 | set { 1307 | self.object = NSNumber(value: newValue) 1308 | } 1309 | } 1310 | 1311 | public var int16: Int16? { 1312 | get { 1313 | return self.number?.int16Value 1314 | } 1315 | set { 1316 | if let newValue = newValue { 1317 | self.object = NSNumber(value: newValue) 1318 | } else { 1319 | self.object = NSNull() 1320 | } 1321 | } 1322 | } 1323 | 1324 | public var int16Value: Int16 { 1325 | get { 1326 | return self.numberValue.int16Value 1327 | } 1328 | set { 1329 | self.object = NSNumber(value: newValue) 1330 | } 1331 | } 1332 | 1333 | public var uInt16: UInt16? { 1334 | get { 1335 | return self.number?.uint16Value 1336 | } 1337 | set { 1338 | if let newValue = newValue { 1339 | self.object = NSNumber(value: newValue) 1340 | } else { 1341 | self.object = NSNull() 1342 | } 1343 | } 1344 | } 1345 | 1346 | public var uInt16Value: UInt16 { 1347 | get { 1348 | return self.numberValue.uint16Value 1349 | } 1350 | set { 1351 | self.object = NSNumber(value: newValue) 1352 | } 1353 | } 1354 | 1355 | public var int32: Int32? { 1356 | get { 1357 | return self.number?.int32Value 1358 | } 1359 | set { 1360 | if let newValue = newValue { 1361 | self.object = NSNumber(value: newValue) 1362 | } else { 1363 | self.object = NSNull() 1364 | } 1365 | } 1366 | } 1367 | 1368 | public var int32Value: Int32 { 1369 | get { 1370 | return self.numberValue.int32Value 1371 | } 1372 | set { 1373 | self.object = NSNumber(value: newValue) 1374 | } 1375 | } 1376 | 1377 | public var uInt32: UInt32? { 1378 | get { 1379 | return self.number?.uint32Value 1380 | } 1381 | set { 1382 | if let newValue = newValue { 1383 | self.object = NSNumber(value: newValue) 1384 | } else { 1385 | self.object = NSNull() 1386 | } 1387 | } 1388 | } 1389 | 1390 | public var uInt32Value: UInt32 { 1391 | get { 1392 | return self.numberValue.uint32Value 1393 | } 1394 | set { 1395 | self.object = NSNumber(value: newValue) 1396 | } 1397 | } 1398 | 1399 | public var int64: Int64? { 1400 | get { 1401 | return self.number?.int64Value 1402 | } 1403 | set { 1404 | if let newValue = newValue { 1405 | self.object = NSNumber(value: newValue) 1406 | } else { 1407 | self.object = NSNull() 1408 | } 1409 | } 1410 | } 1411 | 1412 | public var int64Value: Int64 { 1413 | get { 1414 | return self.numberValue.int64Value 1415 | } 1416 | set { 1417 | self.object = NSNumber(value: newValue) 1418 | } 1419 | } 1420 | 1421 | public var uInt64: UInt64? { 1422 | get { 1423 | return self.number?.uint64Value 1424 | } 1425 | set { 1426 | if let newValue = newValue { 1427 | self.object = NSNumber(value: newValue) 1428 | } else { 1429 | self.object = NSNull() 1430 | } 1431 | } 1432 | } 1433 | 1434 | public var uInt64Value: UInt64 { 1435 | get { 1436 | return self.numberValue.uint64Value 1437 | } 1438 | set { 1439 | self.object = NSNumber(value: newValue) 1440 | } 1441 | } 1442 | } 1443 | 1444 | //MARK: - Comparable 1445 | extension JSON : Swift.Comparable {} 1446 | 1447 | public func ==(lhs: JSON, rhs: JSON) -> Bool { 1448 | 1449 | switch (lhs.type, rhs.type) { 1450 | case (.number, .number): 1451 | return lhs.rawNumber == rhs.rawNumber 1452 | case (.string, .string): 1453 | return lhs.rawString == rhs.rawString 1454 | case (.bool, .bool): 1455 | return lhs.rawBool == rhs.rawBool 1456 | case (.array, .array): 1457 | #if os(Linux) 1458 | return lhs.rawArray._bridgeToObjectiveC() == rhs.rawArray._bridgeToObjectiveC() 1459 | #else 1460 | return lhs.rawArray as NSArray == rhs.rawArray as NSArray 1461 | #endif 1462 | case (.dictionary, .dictionary): 1463 | #if os(Linux) 1464 | return lhs.rawDictionary._bridgeToObjectiveC() == rhs.rawDictionary._bridgeToObjectiveC() 1465 | #else 1466 | return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary 1467 | #endif 1468 | case (.null, .null): 1469 | return true 1470 | default: 1471 | return false 1472 | } 1473 | } 1474 | 1475 | public func <=(lhs: JSON, rhs: JSON) -> Bool { 1476 | 1477 | switch (lhs.type, rhs.type) { 1478 | case (.number, .number): 1479 | return lhs.rawNumber <= rhs.rawNumber 1480 | case (.string, .string): 1481 | return lhs.rawString <= rhs.rawString 1482 | case (.bool, .bool): 1483 | return lhs.rawBool == rhs.rawBool 1484 | case (.array, .array): 1485 | #if os(Linux) 1486 | return lhs.rawArray._bridgeToObjectiveC() == rhs.rawArray._bridgeToObjectiveC() 1487 | #else 1488 | return lhs.rawArray as NSArray == rhs.rawArray as NSArray 1489 | #endif 1490 | case (.dictionary, .dictionary): 1491 | #if os(Linux) 1492 | return lhs.rawDictionary._bridgeToObjectiveC() == rhs.rawDictionary._bridgeToObjectiveC() 1493 | #else 1494 | return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary 1495 | #endif 1496 | case (.null, .null): 1497 | return true 1498 | default: 1499 | return false 1500 | } 1501 | } 1502 | 1503 | public func >=(lhs: JSON, rhs: JSON) -> Bool { 1504 | 1505 | switch (lhs.type, rhs.type) { 1506 | case (.number, .number): 1507 | return lhs.rawNumber >= rhs.rawNumber 1508 | case (.string, .string): 1509 | return lhs.rawString >= rhs.rawString 1510 | case (.bool, .bool): 1511 | return lhs.rawBool == rhs.rawBool 1512 | case (.array, .array): 1513 | #if os(Linux) 1514 | return lhs.rawArray._bridgeToObjectiveC() == rhs.rawArray._bridgeToObjectiveC() 1515 | #else 1516 | return lhs.rawArray as NSArray == rhs.rawArray as NSArray 1517 | #endif 1518 | case (.dictionary, .dictionary): 1519 | #if os(Linux) 1520 | return lhs.rawDictionary._bridgeToObjectiveC() == rhs.rawDictionary._bridgeToObjectiveC() 1521 | #else 1522 | return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary 1523 | #endif 1524 | case (.null, .null): 1525 | return true 1526 | default: 1527 | return false 1528 | } 1529 | } 1530 | 1531 | public func >(lhs: JSON, rhs: JSON) -> Bool { 1532 | 1533 | switch (lhs.type, rhs.type) { 1534 | case (.number, .number): 1535 | return lhs.rawNumber > rhs.rawNumber 1536 | case (.string, .string): 1537 | return lhs.rawString > rhs.rawString 1538 | default: 1539 | return false 1540 | } 1541 | } 1542 | 1543 | public func <(lhs: JSON, rhs: JSON) -> Bool { 1544 | 1545 | switch (lhs.type, rhs.type) { 1546 | case (.number, .number): 1547 | return lhs.rawNumber < rhs.rawNumber 1548 | case (.string, .string): 1549 | return lhs.rawString < rhs.rawString 1550 | default: 1551 | return false 1552 | } 1553 | } 1554 | 1555 | private let trueNumber = NSNumber(value: true) 1556 | private let falseNumber = NSNumber(value: false) 1557 | private let trueObjCType = String(describing: trueNumber.objCType) 1558 | private let falseObjCType = String(describing: falseNumber.objCType) 1559 | 1560 | // MARK: - NSNumber: Comparable 1561 | 1562 | extension NSNumber { 1563 | var isBool:Bool { 1564 | get { 1565 | #if os(Linux) 1566 | let type = CFNumberGetType(unsafeBitCast(self, to: CFNumber.self)) 1567 | if type == kCFNumberSInt8Type && 1568 | (self.compare(trueNumber) == ComparisonResult.orderedSame || 1569 | self.compare(falseNumber) == ComparisonResult.orderedSame){ 1570 | return true 1571 | } else { 1572 | return false 1573 | } 1574 | #else 1575 | let objCType = String(describing: self.objCType) 1576 | if (self.compare(trueNumber) == ComparisonResult.orderedSame && objCType == trueObjCType) 1577 | || (self.compare(falseNumber) == ComparisonResult.orderedSame && objCType == falseObjCType){ 1578 | return true 1579 | } else { 1580 | return false 1581 | } 1582 | #endif 1583 | } 1584 | } 1585 | } 1586 | 1587 | func ==(lhs: NSNumber, rhs: NSNumber) -> Bool { 1588 | switch (lhs.isBool, rhs.isBool) { 1589 | case (false, true): 1590 | return false 1591 | case (true, false): 1592 | return false 1593 | default: 1594 | return lhs.compare(rhs) == ComparisonResult.orderedSame 1595 | } 1596 | } 1597 | 1598 | func !=(lhs: NSNumber, rhs: NSNumber) -> Bool { 1599 | return !(lhs == rhs) 1600 | } 1601 | #if os(Linux) && swift(>=5.1) 1602 | // TODO: why must this be excluded, only on Linux, with Swift 5.1? 1603 | #else 1604 | func <(lhs: NSNumber, rhs: NSNumber) -> Bool { 1605 | 1606 | switch (lhs.isBool, rhs.isBool) { 1607 | case (false, true): 1608 | return false 1609 | case (true, false): 1610 | return false 1611 | default: 1612 | return lhs.compare(rhs) == ComparisonResult.orderedAscending 1613 | } 1614 | } 1615 | #endif 1616 | func >(lhs: NSNumber, rhs: NSNumber) -> Bool { 1617 | 1618 | switch (lhs.isBool, rhs.isBool) { 1619 | case (false, true): 1620 | return false 1621 | case (true, false): 1622 | return false 1623 | default: 1624 | return lhs.compare(rhs) == ComparisonResult.orderedDescending 1625 | } 1626 | } 1627 | 1628 | func <=(lhs: NSNumber, rhs: NSNumber) -> Bool { 1629 | 1630 | switch (lhs.isBool, rhs.isBool) { 1631 | case (false, true): 1632 | return false 1633 | case (true, false): 1634 | return false 1635 | default: 1636 | return lhs.compare(rhs) != ComparisonResult.orderedDescending 1637 | } 1638 | } 1639 | 1640 | func >=(lhs: NSNumber, rhs: NSNumber) -> Bool { 1641 | 1642 | switch (lhs.isBool, rhs.isBool) { 1643 | case (false, true): 1644 | return false 1645 | case (true, false): 1646 | return false 1647 | default: 1648 | return lhs.compare(rhs) != ComparisonResult.orderedAscending 1649 | 1650 | } 1651 | } 1652 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright IBM Corporation 2016 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | import XCTest 18 | 19 | @testable import SwiftyJSONTests 20 | 21 | XCTMain([ 22 | testCase(ArrayTests.allTests), 23 | testCase(BaseTests.allTests), 24 | testCase(ComparableTests.allTests), 25 | testCase(DictionaryTests.allTests), 26 | testCase(LiteralConvertibleTests.allTests), 27 | testCase(NumberTests.allTests), 28 | testCase(PerformanceTests.allTests), 29 | testCase(PrintableTests.allTests), 30 | testCase(RawRepresentableTests.allTests), 31 | testCase(RawTests.allTests), 32 | testCase(SequenceTypeTests.allTests), 33 | testCase(StringTests.allTests), 34 | testCase(SubscriptTests.allTests) 35 | ]) 36 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/ArrayTests.swift: -------------------------------------------------------------------------------- 1 | // ArrayTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | @testable import SwiftyJSON 25 | 26 | class ArrayTests: XCTestCase { 27 | 28 | // GENERATED: allTests required for Swift 3.0 29 | static var allTests : [(String, (ArrayTests) -> () throws -> Void)] { 30 | return [ 31 | ("testSingleDimensionalArraysGetter", testSingleDimensionalArraysGetter), 32 | ("testSingleDimensionalArraysSetter", testSingleDimensionalArraysSetter), 33 | ] 34 | } 35 | // END OF GENERATED CODE 36 | 37 | func testSingleDimensionalArraysGetter() { 38 | let array = ["1","2", "a", "B", "D"] 39 | let json = JSON(array as Any) 40 | 41 | XCTAssertEqual((json.array![0] as JSON).string!, "1") 42 | XCTAssertEqual((json.array![1] as JSON).string!, "2") 43 | XCTAssertEqual((json.array![2] as JSON).string!, "a") 44 | XCTAssertEqual((json.array![3] as JSON).string!, "B") 45 | XCTAssertEqual((json.array![4] as JSON).string!, "D") 46 | } 47 | 48 | func testSingleDimensionalArraysSetter() { 49 | let array = ["1","2", "a", "B", "D"] 50 | var json = JSON(array as Any) 51 | 52 | json.arrayObject = ["111", "222"] 53 | XCTAssertEqual((json.array![0] as JSON).string!, "111") 54 | XCTAssertEqual((json.array![1] as JSON).string!, "222") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/BaseTests.swift: -------------------------------------------------------------------------------- 1 | // BaseTests.swift 2 | // 3 | // Copyright (c) 2014 Ruoyu Fu, Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class BaseTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (BaseTests) -> () throws -> Void)] { 32 | return [ 33 | ("testInit", testInit), 34 | ("testCompare", testCompare), 35 | ("testJSONDoesProduceValidWithCorrectKeyPath", testJSONDoesProduceValidWithCorrectKeyPath), 36 | ("testSequenceType", testSequenceType), 37 | ("testJSONNumberCompare", testJSONNumberCompare), 38 | ("testNumberConvertToString", testNumberConvertToString), 39 | ("testNumberPrint", testNumberPrint), 40 | ("testNullJSON", testNullJSON), 41 | ("testExistance", testExistance), 42 | ("testErrorHandle", testErrorHandle), 43 | ("testReturnObject", testReturnObject), 44 | ("testNumberCompare", testNumberCompare), 45 | ] 46 | } 47 | // END OF GENERATED CODE 48 | 49 | var testData: Data! 50 | 51 | override func setUp() { 52 | 53 | super.setUp() 54 | 55 | var testDataURL = URL(fileURLWithPath: #file) 56 | testDataURL.appendPathComponent("../Tests.json") 57 | do { 58 | self.testData = try Data(contentsOf: testDataURL.standardized) 59 | } 60 | catch { 61 | XCTFail("Failed to read in the test data") 62 | exit(1) 63 | } 64 | } 65 | 66 | override func tearDown() { 67 | super.tearDown() 68 | } 69 | 70 | func testInit() { 71 | let json0 = JSON(data:self.testData) 72 | XCTAssertEqual(json0.array!.count, 3) 73 | XCTAssertEqual(JSON("123").description, "123") 74 | XCTAssertEqual(JSON(["1":"2"])["1"].string!, "2") 75 | let dictionary = NSMutableDictionary() 76 | dictionary.setObject(NSNumber(value: 1.0), forKey: "number" as NSString) 77 | dictionary.setObject(NSNull(), forKey: "null" as NSString) 78 | _ = JSON(dictionary) 79 | do { 80 | let object: Any = try JSONSerialization.jsonObject(with: self.testData, options: []) 81 | let json2 = JSON(object) 82 | XCTAssertEqual(json0, json2) 83 | } catch _ { 84 | } 85 | } 86 | 87 | func testCompare() { 88 | XCTAssertNotEqual(JSON("32.1234567890"), JSON(32.1234567890)) 89 | XCTAssertNotEqual(JSON("9876543210987654321"),JSON(NSNumber(value:9876543210987654321 as UInt64))) 90 | XCTAssertNotEqual(JSON("9876543210987654321.12345678901234567890"), JSON(9876543210987654321.12345678901234567890)) 91 | XCTAssertEqual(JSON("😊"), JSON("😊")) 92 | XCTAssertNotEqual(JSON("😱"), JSON("😁")) 93 | XCTAssertEqual(JSON([123,321,456]), JSON([123,321,456])) 94 | XCTAssertNotEqual(JSON([123,321,456]), JSON(123456789)) 95 | XCTAssertNotEqual(JSON([123,321,456]), JSON("string")) 96 | XCTAssertNotEqual(JSON(["1":123,"2":321,"3":456]), JSON("string")) 97 | XCTAssertEqual(JSON(["1":123,"2":321,"3":456]), JSON(["2":321,"1":123,"3":456])) 98 | XCTAssertEqual(JSON(NSNull()),JSON(NSNull())) 99 | XCTAssertNotEqual(JSON(NSNull()), JSON(123)) 100 | } 101 | 102 | func testJSONDoesProduceValidWithCorrectKeyPath() { 103 | let json = JSON(data:self.testData) 104 | 105 | let tweets = json 106 | let tweets_array = json.array 107 | let tweets_1 = json[1] 108 | _ = tweets_1[1] 109 | let tweets_1_user_name = tweets_1["user"]["name"] 110 | let tweets_1_user_name_string = tweets_1["user"]["name"].string 111 | XCTAssertNotEqual(tweets.type, Type.null) 112 | XCTAssert(tweets_array != nil) 113 | XCTAssertNotEqual(tweets_1.type, Type.null) 114 | XCTAssertEqual(tweets_1_user_name, JSON("Raffi Krikorian")) 115 | XCTAssertEqual(tweets_1_user_name_string!, "Raffi Krikorian") 116 | 117 | let tweets_1_coordinates = tweets_1["coordinates"] 118 | let tweets_1_coordinates_coordinates = tweets_1_coordinates["coordinates"] 119 | let tweets_1_coordinates_coordinates_point_0_double = tweets_1_coordinates_coordinates[0].double 120 | let tweets_1_coordinates_coordinates_point_1_float = tweets_1_coordinates_coordinates[1].float 121 | let new_tweets_1_coordinates_coordinates = JSON([-122.25831,37.871609]) 122 | XCTAssertEqual(tweets_1_coordinates_coordinates, new_tweets_1_coordinates_coordinates) 123 | XCTAssertEqual(tweets_1_coordinates_coordinates_point_0_double!, -122.25831) 124 | XCTAssertTrue(tweets_1_coordinates_coordinates_point_1_float! == 37.871609) 125 | let tweets_1_coordinates_coordinates_point_0_string = tweets_1_coordinates_coordinates[0].stringValue 126 | let tweets_1_coordinates_coordinates_point_1_string = tweets_1_coordinates_coordinates[1].stringValue 127 | XCTAssertEqual(tweets_1_coordinates_coordinates_point_0_string, "-122.25831") 128 | XCTAssertEqual(tweets_1_coordinates_coordinates_point_1_string, "37.871609") 129 | let tweets_1_coordinates_coordinates_point_0 = tweets_1_coordinates_coordinates[0] 130 | let tweets_1_coordinates_coordinates_point_1 = tweets_1_coordinates_coordinates[1] 131 | XCTAssertEqual(tweets_1_coordinates_coordinates_point_0, JSON(-122.25831)) 132 | XCTAssertEqual(tweets_1_coordinates_coordinates_point_1, JSON(37.871609)) 133 | 134 | let created_at = json[0]["created_at"].string 135 | let id_str = json[0]["id_str"].string 136 | let favorited = json[0]["favorited"].bool 137 | let id = json[0]["id"].int64 138 | let in_reply_to_user_id_str = json[0]["in_reply_to_user_id_str"] 139 | XCTAssertEqual(created_at!, "Tue Aug 28 21:16:23 +0000 2012") 140 | XCTAssertEqual(id_str!,"240558470661799936") 141 | XCTAssertFalse(favorited!) 142 | XCTAssertEqual(id!,240558470661799936) 143 | XCTAssertEqual(in_reply_to_user_id_str.type, Type.null) 144 | 145 | let user = json[0]["user"] 146 | let user_name = user["name"].string 147 | let user_profile_image_url = user["profile_image_url"].URL 148 | XCTAssert(user_name == "OAuth Dancer") 149 | XCTAssert(user_profile_image_url == NSURL(string: "http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg")) 150 | 151 | let user_dictionary = json[0]["user"].dictionary 152 | let user_dictionary_name = user_dictionary?["name"]?.string 153 | let user_dictionary_name_profile_image_url = user_dictionary?["profile_image_url"]?.URL 154 | XCTAssert(user_dictionary_name == "OAuth Dancer") 155 | XCTAssert(user_dictionary_name_profile_image_url == NSURL(string: "http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg")) 156 | } 157 | 158 | func testSequenceType() { 159 | let json = JSON(data:self.testData) 160 | XCTAssertEqual(json.count, 3) 161 | for (_, aJson) in json { 162 | XCTAssertEqual(aJson, json[0]) 163 | break 164 | } 165 | 166 | #if !swift(>=5.0) 167 | // Invalid as of Swift 5, as dictionary order is not predictable 168 | let index = 0 169 | let keys = Array(json[1].dictionaryObject!.keys) 170 | for (aKey, aJson) in json[1] { 171 | XCTAssertEqual(aKey, keys[index]) 172 | XCTAssertEqual(aJson, json[1][keys[index]]) 173 | break 174 | } 175 | #endif 176 | } 177 | 178 | func testJSONNumberCompare() { 179 | XCTAssertEqual(JSON(12376352.123321), JSON(12376352.123321)) 180 | XCTAssertGreaterThan(JSON(20.211), JSON(20.112)) 181 | XCTAssertGreaterThanOrEqual(JSON(30.211), JSON(20.112)) 182 | XCTAssertGreaterThanOrEqual(JSON(65232), JSON(65232)) 183 | XCTAssertLessThan(JSON(-82320.211), JSON(20.112)) 184 | XCTAssertLessThanOrEqual(JSON(-320.211), JSON(123.1)) 185 | XCTAssertLessThanOrEqual(JSON(-8763), JSON(-8763)) 186 | 187 | XCTAssertEqual(JSON(12376352.123321), JSON(12376352.123321)) 188 | XCTAssertGreaterThan(JSON(20.211), JSON(20.112)) 189 | XCTAssertGreaterThanOrEqual(JSON(30.211), JSON(20.112)) 190 | XCTAssertGreaterThanOrEqual(JSON(65232), JSON(65232)) 191 | XCTAssertLessThan(JSON(-82320.211), JSON(20.112)) 192 | XCTAssertLessThanOrEqual(JSON(-320.211), JSON(123.1)) 193 | XCTAssertLessThanOrEqual(JSON(-8763), JSON(-8763)) 194 | } 195 | 196 | func testNumberConvertToString(){ 197 | XCTAssertEqual(JSON(true).stringValue, "true") 198 | XCTAssertEqual(JSON(999.9823).stringValue, "999.9823") 199 | XCTAssertEqual(JSON(true).number!.stringValue, "1") 200 | XCTAssertEqual(JSON(false).number!.stringValue, "0") 201 | #if os(Linux) && swift(>=4.2) 202 | // https://github.com/apple/swift-corelibs-foundation/pull/1724 203 | let expectedValue = "0.0" 204 | #else 205 | let expectedValue = "0" 206 | #endif 207 | XCTAssertEqual(JSON("hello").numberValue.stringValue, expectedValue) 208 | XCTAssertEqual(JSON(NSNull()).numberValue.stringValue, expectedValue) 209 | XCTAssertEqual(JSON(["a","b","c","d"]).numberValue.stringValue, expectedValue) 210 | XCTAssertEqual(JSON(["a":"b","c":"d"]).numberValue.stringValue, expectedValue) 211 | } 212 | 213 | func testNumberPrint(){ 214 | 215 | XCTAssertEqual(JSON(false).description,"false") 216 | XCTAssertEqual(JSON(true).description,"true") 217 | 218 | XCTAssertEqual(JSON(1).description,"1") 219 | XCTAssertEqual(JSON(22).description,"22") 220 | #if (arch(x86_64) || arch(arm64)) 221 | XCTAssertEqual(JSON(9.22337203685478E18).description,"9.22337203685478e+18") 222 | #elseif (arch(i386) || arch(arm)) 223 | XCTAssertEqual(JSON(2147483647).description,"2147483647") 224 | #endif 225 | XCTAssertEqual(JSON(-1).description,"-1") 226 | XCTAssertEqual(JSON(-934834834).description,"-934834834") 227 | XCTAssertEqual(JSON(-2147483648).description,"-2147483648") 228 | 229 | XCTAssertEqual(JSON(1.5555).description,"1.5555") 230 | XCTAssertEqual(JSON(-9.123456789).description,"-9.123456789") 231 | XCTAssertEqual(JSON(-0.00000000000000001).description,"-1e-17") 232 | XCTAssertEqual(JSON(-999999999999999999999999.000000000000000000000001).description,"-1e+24") 233 | 234 | #if !os(Linux) 235 | // blocked by defect https://bugs.swift.org/browse/SR-1464?jql=text%20~%20%22NSNumber%22 236 | //TODO: remove ifdef once the defect is resolved 237 | XCTAssertEqual(JSON(-9999999991999999999999999.88888883433343439438493483483943948341).stringValue,"-9.999999991999999e+24") 238 | #endif 239 | 240 | XCTAssertEqual(JSON(NSNumber(value:Int.max)).description,"\(Int.max)") 241 | XCTAssertEqual(JSON(NSNumber(value: Int.min)).description,"\(Int.min)") 242 | XCTAssertEqual(JSON(NSNumber(value: Int64.max)).description,"\(Int64.max)") 243 | 244 | #if !os(Linux) 245 | // blocked by defect https://bugs.swift.org/browse/SR-1464?jql=text%20~%20%22NSNumber%22 246 | //TODO: remove ifdef once the defect is resolved 247 | 248 | XCTAssertEqual(JSON(NSNumber(value: UInt.max)).description,"\(UInt.max)") 249 | XCTAssertEqual(JSON(NSNumber(value: UInt64.max)).description,"\(UInt64.max)") 250 | XCTAssertEqual(JSON(NSNumber(value: UInt64.max)).description,"\(UInt64.max)") 251 | #endif 252 | 253 | XCTAssertEqual(JSON(Double.infinity as Any).description,"inf") 254 | XCTAssertEqual(JSON(-Double.infinity as Any).description,"-inf") 255 | XCTAssertEqual(JSON(Double.nan as Any).description,"nan") 256 | 257 | XCTAssertEqual(JSON(1.0/0.0 as Any).description,"inf") 258 | XCTAssertEqual(JSON(-1.0/0.0 as Any).description,"-inf") 259 | XCTAssertEqual(JSON(0.0/0.0 as Any).description,"nan") 260 | } 261 | 262 | func testNullJSON() { 263 | XCTAssertEqual(JSON(NSNull()).debugDescription,"null") 264 | 265 | let json:JSON = nil 266 | XCTAssertEqual(json.debugDescription,"null") 267 | XCTAssertNil(json.error) 268 | let json1:JSON = JSON(NSNull()) 269 | if json1 != nil { 270 | XCTFail("json1 should be nil") 271 | } 272 | } 273 | 274 | func testExistance() { 275 | let dictionary = ["number":1111] 276 | let json = JSON(dictionary as Any) 277 | 278 | XCTAssertFalse(json["unspecifiedValue"].exists()) 279 | XCTAssertTrue(json["number"].exists()) 280 | } 281 | 282 | func testErrorHandle() { 283 | let json = JSON(data:self.testData) 284 | if let _ = json["wrong-type"].string { 285 | XCTFail("Should not run into here") 286 | } else { 287 | XCTAssertEqual(json["wrong-type"].error!.code, SwiftyJSON.ErrorWrongType) 288 | } 289 | 290 | if let _ = json[0]["not-exist"].string { 291 | XCTFail("Should not run into here") 292 | } else { 293 | XCTAssertEqual(json[0]["not-exist"].error!.code, SwiftyJSON.ErrorNotExist) 294 | } 295 | 296 | let wrongJSON = JSON(NSObject()) 297 | if let error = wrongJSON.error { 298 | XCTAssertEqual(error.code, SwiftyJSON.ErrorUnsupportedType) 299 | } 300 | } 301 | 302 | func testReturnObject() { 303 | let json = JSON(data:self.testData) 304 | XCTAssertNotNil(json.object) 305 | } 306 | 307 | func testNumberCompare(){ 308 | XCTAssertEqual(NSNumber(value: 888332), NSNumber(value:888332)) 309 | XCTAssertNotEqual(NSNumber(value: 888332.1), NSNumber(value:888332)) 310 | XCTAssertLessThan(NSNumber(value: 888332).doubleValue, NSNumber(value:888332.1).doubleValue) 311 | XCTAssertGreaterThan(NSNumber(value: 888332.1).doubleValue, NSNumber(value:888332).doubleValue) 312 | 313 | // Blocked by https://bugs.swift.org/browse/SR-5803 314 | #if !(os(Linux) && swift(>=3.2)) 315 | XCTAssertFalse(NSNumber(value: 1) == NSNumber(value:true)) 316 | XCTAssertFalse(NSNumber(value: 0) == NSNumber(value:false)) 317 | #endif 318 | 319 | XCTAssertEqual(NSNumber(value: false), NSNumber(value:false)) 320 | XCTAssertEqual(NSNumber(value: true), NSNumber(value:true)) 321 | } 322 | 323 | 324 | } 325 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/ComparableTests.swift: -------------------------------------------------------------------------------- 1 | // ComparableTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class ComparableTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (ComparableTests) -> () throws -> Void)] { 32 | return [ 33 | ("testNumberEqual", testNumberEqual), 34 | ("testNumberNotEqual", testNumberNotEqual), 35 | ("testNumberGreaterThanOrEqual", testNumberGreaterThanOrEqual), 36 | ("testNumberLessThanOrEqual", testNumberLessThanOrEqual), 37 | ("testNumberGreaterThan", testNumberGreaterThan), 38 | ("testNumberLessThan", testNumberLessThan), 39 | ("testBoolEqual", testBoolEqual), 40 | ("testBoolNotEqual", testBoolNotEqual), 41 | ("testBoolGreaterThanOrEqual", testBoolGreaterThanOrEqual), 42 | ("testBoolLessThanOrEqual", testBoolLessThanOrEqual), 43 | ("testBoolGreaterThan", testBoolGreaterThan), 44 | ("testBoolLessThan", testBoolLessThan), 45 | ("testStringEqual", testStringEqual), 46 | ("testStringNotEqual", testStringNotEqual), 47 | ("testStringGreaterThanOrEqual", testStringGreaterThanOrEqual), 48 | ("testStringLessThanOrEqual", testStringLessThanOrEqual), 49 | ("testStringGreaterThan", testStringGreaterThan), 50 | ("testStringLessThan", testStringLessThan), 51 | ("testNil", testNil), 52 | ("testArray", testArray), 53 | ("testDictionary", testDictionary), 54 | ] 55 | } 56 | // END OF GENERATED CODE 57 | 58 | func testNumberEqual() { 59 | let jsonL1:JSON = 1234567890.876623 60 | let jsonR1:JSON = JSON(1234567890.876623) 61 | XCTAssertEqual(jsonL1, jsonR1) 62 | XCTAssertTrue(jsonL1 == 1234567890.876623) 63 | 64 | let jsonL2:JSON = 987654321 65 | let jsonR2:JSON = JSON(987654321) 66 | XCTAssertEqual(jsonL2, jsonR2) 67 | XCTAssertTrue(jsonR2 == 987654321) 68 | 69 | 70 | let jsonL3:JSON = JSON(NSNumber(value:87654321.12345678)) 71 | let jsonR3:JSON = JSON(NSNumber(value:87654321.12345678)) 72 | XCTAssertEqual(jsonL3, jsonR3) 73 | XCTAssertTrue(jsonR3 == 87654321.12345678) 74 | } 75 | 76 | func testNumberNotEqual() { 77 | let jsonL1:JSON = 1234567890.876623 78 | let jsonR1:JSON = JSON(123.123) 79 | XCTAssertNotEqual(jsonL1, jsonR1) 80 | XCTAssertFalse(jsonL1 == 34343) 81 | 82 | let jsonL2:JSON = 8773 83 | let jsonR2:JSON = JSON(123.23) 84 | XCTAssertNotEqual(jsonL2, jsonR2) 85 | XCTAssertFalse(jsonR1 == 454352) 86 | 87 | let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) 88 | let jsonR3:JSON = JSON(NSNumber(value:87654321.45678)) 89 | XCTAssertNotEqual(jsonL3, jsonR3) 90 | XCTAssertFalse(jsonL3 == 4545.232) 91 | } 92 | 93 | func testNumberGreaterThanOrEqual() { 94 | let jsonL1:JSON = 1234567890.876623 95 | let jsonR1:JSON = JSON(123.123) 96 | XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) 97 | XCTAssertTrue(jsonL1 >= -37434) 98 | 99 | let jsonL2:JSON = 8773 100 | let jsonR2:JSON = JSON(-87343) 101 | XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) 102 | XCTAssertTrue(jsonR2 >= -988343) 103 | 104 | let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) 105 | let jsonR3:JSON = JSON(NSNumber(value:87621.12345678)) 106 | XCTAssertGreaterThanOrEqual(jsonL3, jsonR3) 107 | XCTAssertTrue(jsonR3 >= 0.3232) 108 | } 109 | 110 | func testNumberLessThanOrEqual() { 111 | let jsonL1:JSON = 1234567890.876623 112 | let jsonR1:JSON = JSON(123.123) 113 | XCTAssertLessThanOrEqual(jsonR1, jsonL1) 114 | XCTAssertFalse(83487343.3493 <= jsonR1) 115 | 116 | let jsonL2:JSON = 8773 117 | let jsonR2:JSON = JSON(-123.23) 118 | XCTAssertLessThanOrEqual(jsonR2, jsonL2) 119 | XCTAssertFalse(9348343 <= jsonR2) 120 | 121 | let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) 122 | let jsonR3:JSON = JSON(NSNumber(value:87621.12345678)) 123 | XCTAssertLessThanOrEqual(jsonR3, jsonL3) 124 | XCTAssertTrue(87621.12345678 <= jsonR3) 125 | } 126 | 127 | func testNumberGreaterThan() { 128 | let jsonL1:JSON = 1234567890.876623 129 | let jsonR1:JSON = JSON(123.123) 130 | XCTAssertGreaterThan(jsonL1, jsonR1) 131 | XCTAssertFalse(jsonR1 > 192388843.0988) 132 | 133 | let jsonL2:JSON = 8773 134 | let jsonR2:JSON = JSON(123.23) 135 | XCTAssertGreaterThan(jsonL2, jsonR2) 136 | XCTAssertFalse(jsonR2 > 877434) 137 | 138 | let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) 139 | let jsonR3:JSON = JSON(NSNumber(value:87621.1234567)) 140 | XCTAssertGreaterThan(jsonL3, jsonR3) 141 | XCTAssertFalse(-7799 > jsonR3) 142 | } 143 | 144 | func testNumberLessThan() { 145 | let jsonL1:JSON = 1234567890.876623 146 | let jsonR1:JSON = JSON(123.123) 147 | XCTAssertLessThan(jsonR1, jsonL1) 148 | XCTAssertTrue(jsonR1 < 192388843.0988) 149 | 150 | let jsonL2:JSON = 8773 151 | let jsonR2:JSON = JSON(123.23) 152 | XCTAssertLessThan(jsonR2, jsonL2) 153 | XCTAssertTrue(jsonR2 < 877434) 154 | 155 | let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) 156 | let jsonR3:JSON = JSON(NSNumber(value:87621.1234567)) 157 | XCTAssertLessThan(jsonR3, jsonL3) 158 | XCTAssertTrue(-7799 < jsonR3) 159 | } 160 | 161 | func testBoolEqual() { 162 | let jsonL1:JSON = true 163 | let jsonR1:JSON = JSON(true) 164 | XCTAssertEqual(jsonL1, jsonR1) 165 | XCTAssertTrue(jsonL1 == true) 166 | 167 | let jsonL2:JSON = false 168 | let jsonR2:JSON = JSON(false) 169 | XCTAssertEqual(jsonL2, jsonR2) 170 | XCTAssertTrue(jsonL2 == false) 171 | } 172 | 173 | func testBoolNotEqual() { 174 | let jsonL1:JSON = true 175 | let jsonR1:JSON = JSON(false) 176 | XCTAssertNotEqual(jsonL1, jsonR1) 177 | XCTAssertTrue(jsonL1 != false) 178 | 179 | let jsonL2:JSON = false 180 | let jsonR2:JSON = JSON(true) 181 | XCTAssertNotEqual(jsonL2, jsonR2) 182 | XCTAssertTrue(jsonL2 != true) 183 | } 184 | 185 | func testBoolGreaterThanOrEqual() { 186 | let jsonL1:JSON = true 187 | let jsonR1:JSON = JSON(true) 188 | XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) 189 | XCTAssertTrue(jsonL1 >= true) 190 | 191 | let jsonL2:JSON = false 192 | let jsonR2:JSON = JSON(false) 193 | XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) 194 | XCTAssertFalse(jsonL2 >= true) 195 | } 196 | 197 | func testBoolLessThanOrEqual() { 198 | let jsonL1:JSON = true 199 | let jsonR1:JSON = JSON(true) 200 | XCTAssertLessThanOrEqual(jsonL1, jsonR1) 201 | XCTAssertTrue(true <= jsonR1) 202 | 203 | let jsonL2:JSON = false 204 | let jsonR2:JSON = JSON(false) 205 | XCTAssertLessThanOrEqual(jsonL2, jsonR2) 206 | XCTAssertFalse(jsonL2 <= true) 207 | } 208 | 209 | func testBoolGreaterThan() { 210 | let jsonL1:JSON = true 211 | let jsonR1:JSON = JSON(true) 212 | XCTAssertFalse(jsonL1 > jsonR1) 213 | XCTAssertFalse(jsonL1 > true) 214 | XCTAssertFalse(jsonR1 > false) 215 | 216 | let jsonL2:JSON = false 217 | let jsonR2:JSON = JSON(false) 218 | XCTAssertFalse(jsonL2 > jsonR2) 219 | XCTAssertFalse(jsonL2 > false) 220 | XCTAssertFalse(jsonR2 > true) 221 | 222 | let jsonL3:JSON = true 223 | let jsonR3:JSON = JSON(false) 224 | XCTAssertFalse(jsonL3 > jsonR3) 225 | XCTAssertFalse(jsonL3 > false) 226 | XCTAssertFalse(jsonR3 > true) 227 | 228 | let jsonL4:JSON = false 229 | let jsonR4:JSON = JSON(true) 230 | XCTAssertFalse(jsonL4 > jsonR4) 231 | XCTAssertFalse(jsonL4 > false) 232 | XCTAssertFalse(jsonR4 > true) 233 | } 234 | 235 | func testBoolLessThan() { 236 | let jsonL1:JSON = true 237 | let jsonR1:JSON = JSON(true) 238 | XCTAssertFalse(jsonL1 < jsonR1) 239 | XCTAssertFalse(jsonL1 < true) 240 | XCTAssertFalse(jsonR1 < false) 241 | 242 | let jsonL2:JSON = false 243 | let jsonR2:JSON = JSON(false) 244 | XCTAssertFalse(jsonL2 < jsonR2) 245 | XCTAssertFalse(jsonL2 < false) 246 | XCTAssertFalse(jsonR2 < true) 247 | 248 | let jsonL3:JSON = true 249 | let jsonR3:JSON = JSON(false) 250 | XCTAssertFalse(jsonL3 < jsonR3) 251 | XCTAssertFalse(jsonL3 < false) 252 | XCTAssertFalse(jsonR3 < true) 253 | 254 | let jsonL4:JSON = false 255 | let jsonR4:JSON = JSON(true) 256 | XCTAssertFalse(jsonL4 < jsonR4) 257 | XCTAssertFalse(jsonL4 < false) 258 | XCTAssertFalse(true < jsonR4) 259 | } 260 | 261 | func testStringEqual() { 262 | let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" 263 | let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") 264 | 265 | XCTAssertEqual(jsonL1, jsonR1) 266 | XCTAssertTrue(jsonL1 == "abcdefg 123456789 !@#$%^&*()") 267 | } 268 | 269 | func testStringNotEqual() { 270 | let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" 271 | let jsonR1:JSON = JSON("-=[]\\\"987654321") 272 | 273 | XCTAssertNotEqual(jsonL1, jsonR1) 274 | XCTAssertTrue(jsonL1 != "not equal") 275 | } 276 | 277 | func testStringGreaterThanOrEqual() { 278 | let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" 279 | let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") 280 | 281 | XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) 282 | XCTAssertTrue(jsonL1 >= "abcdefg 123456789 !@#$%^&*()") 283 | 284 | let jsonL2:JSON = "z-+{}:" 285 | let jsonR2:JSON = JSON("a<>?:") 286 | XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) 287 | XCTAssertTrue(jsonL2 >= "mnbvcxz") 288 | } 289 | 290 | func testStringLessThanOrEqual() { 291 | let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" 292 | let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") 293 | 294 | XCTAssertLessThanOrEqual(jsonL1, jsonR1) 295 | XCTAssertTrue(jsonL1 <= "abcdefg 123456789 !@#$%^&*()") 296 | 297 | let jsonL2:JSON = "z-+{}:" 298 | let jsonR2:JSON = JSON("a<>?:") 299 | XCTAssertLessThanOrEqual(jsonR2, jsonL2) 300 | XCTAssertTrue("mnbvcxz" <= jsonL2) 301 | } 302 | 303 | func testStringGreaterThan() { 304 | let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" 305 | let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") 306 | 307 | XCTAssertFalse(jsonL1 > jsonR1) 308 | XCTAssertFalse(jsonL1 > "abcdefg 123456789 !@#$%^&*()") 309 | 310 | let jsonL2:JSON = "z-+{}:" 311 | let jsonR2:JSON = JSON("a<>?:") 312 | XCTAssertGreaterThan(jsonL2, jsonR2) 313 | XCTAssertFalse("87663434" > jsonL2) 314 | } 315 | 316 | func testStringLessThan() { 317 | let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" 318 | let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") 319 | 320 | XCTAssertFalse(jsonL1 < jsonR1) 321 | XCTAssertFalse(jsonL1 < "abcdefg 123456789 !@#$%^&*()") 322 | 323 | let jsonL2:JSON = "98774" 324 | let jsonR2:JSON = JSON("123456") 325 | XCTAssertLessThan(jsonR2, jsonL2) 326 | XCTAssertFalse(jsonL2 < "09") 327 | } 328 | 329 | func testNil() { 330 | let jsonL1:JSON = nil 331 | let jsonR1:JSON = JSON(NSNull()) 332 | XCTAssertEqual(jsonL1, jsonR1) 333 | XCTAssertTrue(jsonL1 != "123") 334 | XCTAssertFalse(jsonL1 > "abcd") 335 | XCTAssertFalse(jsonR1 < "*&^") 336 | XCTAssertFalse(jsonL1 >= "jhfid") 337 | XCTAssertFalse(jsonR1 <= "你好") 338 | XCTAssertTrue(jsonL1 >= jsonR1) 339 | XCTAssertTrue(jsonL1 <= jsonR1) 340 | } 341 | 342 | func testArray() { 343 | let jsonL1:JSON = [1,2,"4",5,"6"] 344 | let jsonR1:JSON = JSON([1,2,"4",5,"6"]) 345 | XCTAssertEqual(jsonL1, jsonR1) 346 | XCTAssertTrue(jsonL1 == [1,2,"4",5,"6"]) 347 | XCTAssertTrue(jsonL1 != ["abcd","efg"]) 348 | XCTAssertTrue(jsonL1 >= jsonR1) 349 | XCTAssertTrue(jsonL1 <= jsonR1) 350 | XCTAssertFalse(jsonL1 > ["abcd",""]) 351 | XCTAssertFalse(jsonR1 < []) 352 | XCTAssertFalse(jsonL1 >= [:]) 353 | } 354 | 355 | func testDictionary() { 356 | let list: [Any] = ["a", 1.09, NSNull()] 357 | 358 | let jsonL1:JSON = ["2": 2, "name": "Jack", "List": list] 359 | let jsonR1:JSON = JSON(["2": 2, "name": "Jack", "List": list] as [String: Any]) 360 | 361 | XCTAssertEqual(jsonL1, jsonR1) 362 | XCTAssertTrue(jsonL1 != ["1":2,"Hello":"World","Koo":"Foo"]) 363 | XCTAssertTrue(jsonL1 >= jsonR1) 364 | XCTAssertTrue(jsonL1 <= jsonR1) 365 | XCTAssertFalse(jsonL1 >= [:]) 366 | XCTAssertFalse(jsonR1 <= ["999":"aaaa"]) 367 | XCTAssertFalse(jsonL1 > [")(*&^":1234567]) 368 | XCTAssertFalse(jsonR1 < ["MNHH":"JUYTR"]) 369 | } 370 | } 371 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/DictionaryTests.swift: -------------------------------------------------------------------------------- 1 | // DictionaryTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | 25 | @testable import SwiftyJSON 26 | 27 | class DictionaryTests: XCTestCase { 28 | 29 | // GENERATED: allTests required for Swift 3.0 30 | static var allTests : [(String, (DictionaryTests) -> () throws -> Void)] { 31 | return [ 32 | ("testGetter", testGetter), 33 | ("testSetter", testSetter), 34 | ] 35 | } 36 | // END OF GENERATED CODE 37 | 38 | func testGetter() { 39 | let subDictionary: [String: Any] = ["sub_number":877.2323, "sub_name":"sub_name"] 40 | let dictionary: [String: Any] = ["number":9823.212, "name":"NAME", "list":[1234, 4.212], "object": subDictionary, "bool":true] 41 | let json = JSON(dictionary as Any) 42 | 43 | //dictionary 44 | XCTAssertEqual((json.dictionary!["number"]! as JSON).double!, 9823.212) 45 | XCTAssertEqual((json.dictionary!["name"]! as JSON).string!, "NAME") 46 | XCTAssertEqual(((json.dictionary!["list"]! as JSON).array![0] as JSON).int!, 1234) 47 | XCTAssertEqual(((json.dictionary!["list"]! as JSON).array![1] as JSON).double!, 4.212) 48 | XCTAssertEqual((((json.dictionary!["object"]! as JSON).dictionaryValue)["sub_number"]! as JSON).double!, 877.2323) 49 | XCTAssertTrue(json.dictionary!["null"] == nil) 50 | //dictionaryValue 51 | XCTAssertEqual(((((json.dictionaryValue)["object"]! as JSON).dictionaryValue)["sub_name"]! as JSON).string!, "sub_name") 52 | XCTAssertEqual((json.dictionaryValue["bool"]! as JSON).bool!, true) 53 | XCTAssertTrue(json.dictionaryValue["null"] == nil) 54 | XCTAssertTrue(JSON.null.dictionaryValue == [:]) 55 | //dictionaryObject 56 | XCTAssertEqual(json.dictionaryObject!["number"]! as? Double, 9823.212) 57 | XCTAssertTrue(json.dictionaryObject!["null"] == nil) 58 | XCTAssertTrue(JSON.null.dictionaryObject == nil) 59 | } 60 | 61 | func testSetter() { 62 | var json:JSON = ["test":"case"] 63 | XCTAssertEqual(convert(json.dictionaryObject), ["test":"case"]) 64 | json.dictionaryObject = ["name":"NAME"] 65 | XCTAssertEqual(convert(json.dictionaryObject), ["name":"NAME"]) 66 | } 67 | 68 | private func convert(_ dictionary: [String: Any]?) -> [String: String] { 69 | var dictionaryToReturn = [String: String]() 70 | 71 | guard let dictionary = dictionary else { 72 | return dictionaryToReturn 73 | } 74 | 75 | for (key, value) in dictionary { 76 | if let stringValue = value as? String { 77 | dictionaryToReturn[key] = stringValue 78 | } 79 | } 80 | 81 | return dictionaryToReturn 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/Info-OSX.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/Info-iOS.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/Info-tvOS.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/LiteralConvertibleTests.swift: -------------------------------------------------------------------------------- 1 | // LiteralConvertibleTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class LiteralConvertibleTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (LiteralConvertibleTests) -> () throws -> Void)] { 32 | return [ 33 | ("testNumber", testNumber), 34 | ("testBool", testBool), 35 | ("testString", testString), 36 | ("testNil", testNil), 37 | ("testArray", testArray), 38 | ("testDictionary", testDictionary), 39 | ] 40 | } 41 | // END OF GENERATED CODE 42 | 43 | func testNumber() { 44 | let json:JSON = 1234567890.876623 45 | XCTAssertEqual(json.int!, 1234567890) 46 | XCTAssertEqual(json.intValue, 1234567890) 47 | XCTAssertEqual(json.double!, 1234567890.876623) 48 | XCTAssertEqual(json.doubleValue, 1234567890.876623) 49 | XCTAssertTrue(json.float! == 1234567890.876623) 50 | XCTAssertTrue(json.floatValue == 1234567890.876623) 51 | } 52 | 53 | func testBool() { 54 | let jsonTrue:JSON = true 55 | XCTAssertEqual(jsonTrue.bool!, true) 56 | XCTAssertEqual(jsonTrue.boolValue, true) 57 | let jsonFalse:JSON = false 58 | XCTAssertEqual(jsonFalse.bool!, false) 59 | XCTAssertEqual(jsonFalse.boolValue, false) 60 | } 61 | 62 | func testString() { 63 | let json:JSON = "abcd efg, HIJK;LMn" 64 | XCTAssertEqual(json.string!, "abcd efg, HIJK;LMn") 65 | XCTAssertEqual(json.stringValue, "abcd efg, HIJK;LMn") 66 | } 67 | 68 | func testNil() { 69 | let jsonNil_1:JSON = nil 70 | XCTAssert(jsonNil_1 == nil) 71 | let jsonNil_2:JSON = JSON(NSNull.self) 72 | XCTAssert(jsonNil_2 != nil) 73 | let jsonNil_3:JSON = JSON(["1":2]) 74 | XCTAssert(jsonNil_3 != nil) 75 | } 76 | 77 | func testArray() { 78 | let json:JSON = [1,2,"4",5,"6"] 79 | XCTAssertEqual(json.array!, [1,2,"4",5,"6"]) 80 | XCTAssertEqual(json.arrayValue, [1,2,"4",5,"6"]) 81 | } 82 | 83 | func testDictionary() { 84 | let json:JSON = ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]] 85 | XCTAssertEqual(json.dictionary!, ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]]) 86 | XCTAssertEqual(json.dictionaryValue, ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]]) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/NumberTests.swift: -------------------------------------------------------------------------------- 1 | // NumberTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class NumberTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (NumberTests) -> () throws -> Void)] { 32 | return [ 33 | ("testNumber", testNumber), 34 | ("testBool", testBool), 35 | ("testDouble", testDouble), 36 | ("testFloat", testFloat), 37 | ("testInt", testInt), 38 | ("testUInt", testUInt), 39 | ("testInt8", testInt8), 40 | ("testUInt8", testUInt8), 41 | ("testInt16", testInt16), 42 | ("testUInt16", testUInt16), 43 | ("testInt32", testInt32), 44 | ("testUInt32", testUInt32), 45 | ("testInt64", testInt64), 46 | ("testUInt64", testUInt64), 47 | ] 48 | } 49 | // END OF GENERATED CODE 50 | 51 | func testNumber() { 52 | //getter 53 | var json = JSON(NSNumber(value: 9876543210.123456789)) 54 | XCTAssertEqual(json.number!, 9876543210.123456789) 55 | XCTAssertEqual(json.numberValue, 9876543210.123456789) 56 | // Number of fraction digits differs on OSX and Linux, 57 | // issue https://github.com/IBM-Swift/SwiftRuntime/issues/183 58 | #if (os(Linux) && !swift(>=4.2)) 59 | XCTAssertEqual(json.stringValue, "9876543210.12346") 60 | #else 61 | XCTAssertEqual(json.stringValue, "9876543210.123457") 62 | #endif 63 | 64 | json.string = "1000000000000000000000000000.1" 65 | XCTAssertNil(json.number) 66 | 67 | #if !os(Linux) 68 | // blocked by defect https://bugs.swift.org/browse/SR-1464?jql=text%20~%20%22NSNumber%22 69 | //TODO: remove ifdef once the defect is resolved 70 | XCTAssertEqual(json.numberValue.description, "1000000000000000000000000000.1") 71 | #endif 72 | 73 | json.string = "1e+27" 74 | #if os(Linux) && swift(>=4.2) 75 | // TODO: is this actually correct? 76 | let expectedValue="1e+27" 77 | #else 78 | let expectedValue="1000000000000000000000000000" 79 | #endif 80 | XCTAssertEqual(json.numberValue.description, expectedValue) 81 | 82 | //setter 83 | json.number = NSNumber(value: 123456789.0987654321) 84 | XCTAssertEqual(json.number!, 123456789.0987654321) 85 | XCTAssertEqual(json.numberValue, 123456789.0987654321) 86 | 87 | json.number = nil 88 | XCTAssertEqual(json.numberValue, 0) 89 | XCTAssertEqual(json.object as? NSNull, NSNull()) 90 | XCTAssertTrue(json.number == nil) 91 | 92 | json.numberValue = 2.9876 93 | XCTAssertEqual(json.number!, 2.9876) 94 | } 95 | 96 | func testBool() { 97 | var json = JSON(true) 98 | XCTAssertEqual(json.bool!, true) 99 | XCTAssertEqual(json.boolValue, true) 100 | 101 | // Blocked by https://bugs.swift.org/browse/SR-5803 102 | #if !(os(Linux) && swift(>=3.2)) 103 | XCTAssertEqual(json.numberValue, true as NSNumber) 104 | #endif 105 | XCTAssertEqual(json.stringValue, "true") 106 | 107 | json.bool = false 108 | XCTAssertEqual(json.bool!, false) 109 | XCTAssertEqual(json.boolValue, false) 110 | 111 | // Blocked by https://bugs.swift.org/browse/SR-5803 112 | #if !(os(Linux) && swift(>=3.2)) 113 | XCTAssertEqual(json.numberValue, false as NSNumber) 114 | #endif 115 | 116 | json.bool = nil 117 | XCTAssertTrue(json.bool == nil) 118 | XCTAssertEqual(json.boolValue, false) 119 | XCTAssertEqual(json.numberValue, 0) 120 | 121 | json.boolValue = true 122 | XCTAssertEqual(json.bool!, true) 123 | XCTAssertEqual(json.boolValue, true) 124 | 125 | // Blocked by https://bugs.swift.org/browse/SR-5803 126 | #if !(os(Linux) && swift(>=3.2)) 127 | XCTAssertEqual(json.numberValue, true as NSNumber) 128 | #endif 129 | } 130 | 131 | func testDouble() { 132 | var json = JSON(9876543210.123456789) 133 | XCTAssertEqual(json.double!, 9876543210.123456789) 134 | XCTAssertEqual(json.doubleValue, 9876543210.123456789) 135 | XCTAssertEqual(json.numberValue, 9876543210.123456789) 136 | // Number of fraction digits differs on OSX and Linux, 137 | // issue https://github.com/IBM-Swift/SwiftRuntime/issues/183 138 | #if (os(Linux) && !swift(>=4.2)) 139 | XCTAssertEqual(json.stringValue, "9876543210.12346") 140 | #else 141 | XCTAssertEqual(json.stringValue, "9876543210.123457") 142 | #endif 143 | 144 | json.double = 2.8765432 145 | XCTAssertEqual(json.double!, 2.8765432) 146 | XCTAssertEqual(json.doubleValue, 2.8765432) 147 | XCTAssertEqual(json.numberValue, 2.8765432) 148 | 149 | json.doubleValue = 89.0987654 150 | XCTAssertEqual(json.double!, 89.0987654) 151 | XCTAssertEqual(json.doubleValue, 89.0987654) 152 | XCTAssertEqual(json.numberValue, 89.0987654) 153 | 154 | json.double = nil 155 | XCTAssertEqual(json.boolValue, false) 156 | XCTAssertEqual(json.doubleValue, 0.0) 157 | XCTAssertEqual(json.numberValue, 0) 158 | } 159 | 160 | func testFloat() { 161 | var json = JSON(54321.12345) 162 | XCTAssertTrue(json.float! == 54321.12345) 163 | XCTAssertTrue(json.floatValue == 54321.12345) 164 | XCTAssertEqual(json.numberValue, 54321.12345) 165 | XCTAssertEqual(json.stringValue, "54321.12345") 166 | 167 | json.float = 23231.65 168 | XCTAssertTrue(json.float! == 23231.65) 169 | XCTAssertTrue(json.floatValue == 23231.65) 170 | 171 | #if swift(>=3.2) 172 | XCTAssertEqual(json.numberValue.doubleValue, 23231.65, accuracy: 0.001) 173 | #else 174 | XCTAssertEqualWithAccuracy(json.numberValue.doubleValue, 23231.65, accuracy: 0.001) 175 | #endif 176 | 177 | 178 | json.floatValue = -98766.23 179 | XCTAssertEqual(json.float!, -98766.23) 180 | XCTAssertEqual(json.floatValue, -98766.23) 181 | 182 | #if swift(>=3.2) 183 | XCTAssertEqual(json.numberValue.doubleValue, -98766.23, accuracy: 0.05) 184 | #else 185 | XCTAssertEqualWithAccuracy(json.numberValue.doubleValue, -98766.23, accuracy: 0.05) 186 | #endif 187 | 188 | } 189 | 190 | func testInt() { 191 | var json = JSON(123456789) 192 | XCTAssertEqual(json.int!, 123456789) 193 | XCTAssertEqual(json.intValue, 123456789) 194 | XCTAssertEqual(json.numberValue, NSNumber(value: 123456789)) 195 | XCTAssertEqual(json.stringValue, "123456789") 196 | 197 | json.int = nil 198 | XCTAssertTrue(json.boolValue == false) 199 | XCTAssertTrue(json.intValue == 0) 200 | XCTAssertEqual(json.numberValue, 0) 201 | XCTAssertEqual(json.object as? NSNull, NSNull()) 202 | XCTAssertTrue(json.int == nil) 203 | 204 | json.intValue = 76543 205 | XCTAssertEqual(json.int!, 76543) 206 | XCTAssertEqual(json.intValue, 76543) 207 | XCTAssertEqual(json.numberValue, NSNumber(value: 76543)) 208 | 209 | json.intValue = 98765421 210 | XCTAssertEqual(json.int!, 98765421) 211 | XCTAssertEqual(json.intValue, 98765421) 212 | XCTAssertEqual(json.numberValue, NSNumber(value: 98765421)) 213 | } 214 | 215 | func testUInt() { 216 | var json = JSON(123456789) 217 | XCTAssertTrue(json.uInt! == 123456789) 218 | XCTAssertTrue(json.uIntValue == 123456789) 219 | XCTAssertEqual(json.numberValue, NSNumber(value: 123456789)) 220 | XCTAssertEqual(json.stringValue, "123456789") 221 | 222 | json.uInt = nil 223 | XCTAssertTrue(json.boolValue == false) 224 | XCTAssertTrue(json.uIntValue == 0) 225 | XCTAssertEqual(json.numberValue, 0) 226 | XCTAssertEqual(json.object as? NSNull, NSNull()) 227 | XCTAssertTrue(json.uInt == nil) 228 | 229 | json.uIntValue = 76543 230 | XCTAssertTrue(json.uInt! == 76543) 231 | XCTAssertTrue(json.uIntValue == 76543) 232 | XCTAssertEqual(json.numberValue, NSNumber(value: 76543)) 233 | 234 | json.uIntValue = 98765421 235 | XCTAssertTrue(json.uInt! == 98765421) 236 | XCTAssertTrue(json.uIntValue == 98765421) 237 | XCTAssertEqual(json.numberValue, NSNumber(value: 98765421)) 238 | } 239 | 240 | func testInt8() { 241 | let n127 = NSNumber(value: 127) 242 | var json = JSON(n127) 243 | XCTAssertTrue(json.int8! == n127.int8Value) 244 | XCTAssertTrue(json.int8Value == n127.int8Value) 245 | XCTAssertTrue(json.number! == n127) 246 | XCTAssertEqual(json.numberValue, n127) 247 | XCTAssertEqual(json.stringValue, "127") 248 | 249 | let nm128 = NSNumber(value: -128) 250 | json.int8Value = nm128.int8Value 251 | XCTAssertTrue(json.int8! == nm128.int8Value) 252 | XCTAssertTrue(json.int8Value == nm128.int8Value) 253 | XCTAssertTrue(json.number! == nm128) 254 | XCTAssertEqual(json.numberValue, nm128) 255 | XCTAssertEqual(json.stringValue, "-128") 256 | 257 | let n0 = NSNumber(value: 0 as Int8) 258 | json.int8Value = n0.int8Value 259 | XCTAssertTrue(json.int8! == n0.int8Value) 260 | XCTAssertTrue(json.int8Value == n0.int8Value) 261 | 262 | // Int8s now seem to be a different type. compare failes. 263 | //XCTAssertTrue(json.number! == n0) 264 | 265 | XCTAssertEqual(json.numberValue, n0) 266 | #if (arch(x86_64) || arch(arm64)) 267 | // Blocked by https://bugs.swift.org/browse/SR-5803 268 | #if !(os(Linux) && swift(>=3.2)) 269 | XCTAssertEqual(json.stringValue, "false") 270 | #endif 271 | #elseif (arch(i386) || arch(arm)) 272 | XCTAssertEqual(json.stringValue, "0") 273 | #endif 274 | 275 | 276 | let n1 = NSNumber(value: 1 as Int8) 277 | json.int8Value = n1.int8Value 278 | XCTAssertTrue(json.int8! == n1.int8Value) 279 | XCTAssertTrue(json.int8Value == n1.int8Value) 280 | 281 | // Int8s now seem to be a different type. compare failes. 282 | //XCTAssertTrue(json.number! == n1) 283 | 284 | XCTAssertEqual(json.numberValue, n1) 285 | #if (arch(x86_64) || arch(arm64)) 286 | // Blocked by https://bugs.swift.org/browse/SR-5803 287 | #if !(os(Linux) && swift(>=3.2)) 288 | XCTAssertEqual(json.stringValue, "true") 289 | #endif 290 | #elseif (arch(i386) || arch(arm)) 291 | XCTAssertEqual(json.stringValue, "1") 292 | #endif 293 | } 294 | 295 | func testUInt8() { 296 | let n255 = NSNumber(value: 255) 297 | var json = JSON(n255) 298 | XCTAssertTrue(json.uInt8! == n255.uint8Value) 299 | XCTAssertTrue(json.uInt8Value == n255.uint8Value) 300 | XCTAssertTrue(json.number! == n255) 301 | XCTAssertEqual(json.numberValue, n255) 302 | XCTAssertEqual(json.stringValue, "255") 303 | 304 | let nm2 = NSNumber(value: 2) 305 | json.uInt8Value = nm2.uint8Value 306 | XCTAssertTrue(json.uInt8! == nm2.uint8Value) 307 | XCTAssertTrue(json.uInt8Value == nm2.uint8Value) 308 | XCTAssertTrue(json.number! == nm2) 309 | XCTAssertEqual(json.numberValue, nm2) 310 | XCTAssertEqual(json.stringValue, "2") 311 | 312 | let nm0 = NSNumber(value: 0) 313 | json.uInt8Value = nm0.uint8Value 314 | XCTAssertTrue(json.uInt8! == nm0.uint8Value) 315 | XCTAssertTrue(json.uInt8Value == nm0.uint8Value) 316 | 317 | #if !os(Linux) 318 | // Because of https://github.com/IBM-Swift/SwiftRuntime/issues/185 319 | // the type is Bool instead of Number 320 | XCTAssertTrue(json.number! == nm0) 321 | XCTAssertEqual(json.stringValue, "0") 322 | #endif 323 | XCTAssertEqual(json.numberValue, nm0) 324 | 325 | let nm1 = NSNumber(value: 1) 326 | json.uInt8 = nm1.uint8Value 327 | XCTAssertTrue(json.uInt8! == nm1.uint8Value) 328 | XCTAssertTrue(json.uInt8Value == nm1.uint8Value) 329 | #if !os(Linux) 330 | // Because of https://github.com/IBM-Swift/SwiftRuntime/issues/185 331 | // the type is Bool instead of Number 332 | XCTAssertTrue(json.number! == nm1) 333 | XCTAssertEqual(json.stringValue, "1") 334 | #endif 335 | XCTAssertEqual(json.numberValue, nm1) 336 | } 337 | 338 | func testInt16() { 339 | 340 | let n32767 = NSNumber(value: 32767) 341 | var json = JSON(n32767) 342 | XCTAssertTrue(json.int16! == n32767.int16Value) 343 | XCTAssertTrue(json.int16Value == n32767.int16Value) 344 | XCTAssertTrue(json.number! == n32767) 345 | XCTAssertEqual(json.numberValue, n32767) 346 | XCTAssertEqual(json.stringValue, "32767") 347 | 348 | let nm32768 = NSNumber(value: -32768) 349 | json.int16Value = nm32768.int16Value 350 | XCTAssertTrue(json.int16! == nm32768.int16Value) 351 | XCTAssertTrue(json.int16Value == nm32768.int16Value) 352 | XCTAssertTrue(json.number! == nm32768) 353 | XCTAssertEqual(json.numberValue, nm32768) 354 | XCTAssertEqual(json.stringValue, "-32768") 355 | 356 | let n0 = NSNumber(value: 0) 357 | json.int16Value = n0.int16Value 358 | XCTAssertTrue(json.int16! == n0.int16Value) 359 | XCTAssertTrue(json.int16Value == n0.int16Value) 360 | XCTAssertTrue(json.number! == n0) 361 | XCTAssertEqual(json.numberValue, n0) 362 | XCTAssertEqual(json.stringValue, "0") 363 | 364 | let n1 = NSNumber(value: 1) 365 | json.int16 = n1.int16Value 366 | XCTAssertTrue(json.int16! == n1.int16Value) 367 | XCTAssertTrue(json.int16Value == n1.int16Value) 368 | XCTAssertTrue(json.number! == n1) 369 | XCTAssertEqual(json.numberValue, n1) 370 | XCTAssertEqual(json.stringValue, "1") 371 | } 372 | 373 | func testUInt16() { 374 | 375 | let n65535 = NSNumber(value: 65535) 376 | var json = JSON(n65535) 377 | XCTAssertTrue(json.uInt16! == n65535.uint16Value) 378 | XCTAssertTrue(json.uInt16Value == n65535.uint16Value) 379 | XCTAssertTrue(json.number! == n65535) 380 | XCTAssertEqual(json.numberValue, n65535) 381 | XCTAssertEqual(json.stringValue, "65535") 382 | 383 | let n32767 = NSNumber(value: 32767) 384 | json.uInt16 = n32767.uint16Value 385 | XCTAssertTrue(json.uInt16! == n32767.uint16Value) 386 | XCTAssertTrue(json.uInt16Value == n32767.uint16Value) 387 | XCTAssertTrue(json.number! == n32767) 388 | XCTAssertEqual(json.numberValue, n32767) 389 | XCTAssertEqual(json.stringValue, "32767") 390 | } 391 | 392 | func testInt32() { 393 | let n2147483647 = NSNumber(value: 2147483647) 394 | var json = JSON(n2147483647) 395 | XCTAssertTrue(json.int32! == n2147483647.int32Value) 396 | XCTAssertTrue(json.int32Value == n2147483647.int32Value) 397 | XCTAssertTrue(json.number! == n2147483647) 398 | XCTAssertEqual(json.numberValue, n2147483647) 399 | XCTAssertEqual(json.stringValue, "2147483647") 400 | 401 | let n32767 = NSNumber(value: 32767) 402 | json.int32 = n32767.int32Value 403 | XCTAssertTrue(json.int32! == n32767.int32Value) 404 | XCTAssertTrue(json.int32Value == n32767.int32Value) 405 | XCTAssertTrue(json.number! == n32767) 406 | XCTAssertEqual(json.numberValue, n32767) 407 | XCTAssertEqual(json.stringValue, "32767") 408 | 409 | let nm2147483648 = NSNumber(value: -2147483648) 410 | json.int32Value = nm2147483648.int32Value 411 | XCTAssertTrue(json.int32! == nm2147483648.int32Value) 412 | XCTAssertTrue(json.int32Value == nm2147483648.int32Value) 413 | XCTAssertTrue(json.number! == nm2147483648) 414 | XCTAssertEqual(json.numberValue, nm2147483648) 415 | XCTAssertEqual(json.stringValue, "-2147483648") 416 | } 417 | 418 | func testUInt32() { 419 | let n2147483648 = NSNumber(value: 2147483648) 420 | var json = JSON(n2147483648) 421 | XCTAssertTrue(json.uInt32! == n2147483648.uint32Value) 422 | XCTAssertTrue(json.uInt32Value == n2147483648.uint32Value) 423 | XCTAssertTrue(json.number! == n2147483648) 424 | XCTAssertEqual(json.numberValue, n2147483648) 425 | XCTAssertEqual(json.stringValue, "2147483648") 426 | 427 | let n32767 = NSNumber(value: 32767) 428 | json.uInt32 = n32767.uint32Value 429 | XCTAssertTrue(json.uInt32! == n32767.uint32Value) 430 | XCTAssertTrue(json.uInt32Value == n32767.uint32Value) 431 | XCTAssertTrue(json.number! == n32767) 432 | XCTAssertEqual(json.numberValue, n32767) 433 | XCTAssertEqual(json.stringValue, "32767") 434 | 435 | let n0 = NSNumber(value: 0) 436 | json.uInt32Value = n0.uint32Value 437 | XCTAssertTrue(json.uInt32! == n0.uint32Value) 438 | XCTAssertTrue(json.uInt32Value == n0.uint32Value) 439 | XCTAssertTrue(json.number! == n0) 440 | XCTAssertEqual(json.numberValue, n0) 441 | XCTAssertEqual(json.stringValue, "0") 442 | } 443 | 444 | func testInt64() { 445 | let int64Max = NSNumber(value: Int64.max) 446 | var json = JSON(int64Max) 447 | XCTAssertTrue(json.int64! == int64Max.int64Value) 448 | XCTAssertTrue(json.int64Value == int64Max.int64Value) 449 | XCTAssertTrue(json.number! == int64Max) 450 | XCTAssertEqual(json.numberValue, int64Max) 451 | XCTAssertEqual(json.stringValue, int64Max.stringValue) 452 | 453 | let n32767 = NSNumber(value: 32767) 454 | json.int64 = n32767.int64Value 455 | XCTAssertTrue(json.int64! == n32767.int64Value) 456 | XCTAssertTrue(json.int64Value == n32767.int64Value) 457 | XCTAssertTrue(json.number! == n32767) 458 | XCTAssertEqual(json.numberValue, n32767) 459 | XCTAssertEqual(json.stringValue, "32767") 460 | 461 | let int64Min = NSNumber(value: (Int64.max-1) * -1) 462 | json.int64Value = int64Min.int64Value 463 | XCTAssertTrue(json.int64! == int64Min.int64Value) 464 | XCTAssertTrue(json.int64Value == int64Min.int64Value) 465 | XCTAssertTrue(json.number! == int64Min) 466 | XCTAssertEqual(json.numberValue, int64Min) 467 | XCTAssertEqual(json.stringValue, int64Min.stringValue) 468 | } 469 | 470 | func testUInt64() { 471 | let uInt64Max = NSNumber(value: UInt64.max) 472 | var json = JSON(uInt64Max) 473 | XCTAssertTrue(json.uInt64! == uInt64Max.uint64Value) 474 | XCTAssertTrue(json.uInt64Value == uInt64Max.uint64Value) 475 | XCTAssertTrue(json.number! == uInt64Max) 476 | XCTAssertEqual(json.numberValue, uInt64Max) 477 | #if !os(Linux) 478 | // Fails on Linux from Swift 4.0.3 after SCLF was fixed to correctly Stringify UInt values 479 | // greater than Int64.max - see https://github.com/apple/swift-corelibs-foundation/pull/1196 480 | // We have decided not to fix this in SwiftyJSON for now (see IBM-Swift/SwiftyJSON#40) 481 | XCTAssertEqual(json.stringValue, uInt64Max.stringValue) 482 | #endif 483 | 484 | let n32767 = NSNumber(value: 32767) 485 | json.int64 = n32767.int64Value 486 | XCTAssertTrue(json.int64! == n32767.int64Value) 487 | XCTAssertTrue(json.int64Value == n32767.int64Value) 488 | XCTAssertTrue(json.number! == n32767) 489 | XCTAssertEqual(json.numberValue, n32767) 490 | XCTAssertEqual(json.stringValue, "32767") 491 | } 492 | } 493 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/PerformanceTests.swift: -------------------------------------------------------------------------------- 1 | // PerformanceTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | #if os(Linux) 29 | // autoreleasepool is Objective-C feature 30 | //TODO check what is its equivalent in Swift on Linux 31 | func autoreleasepool(callback:() -> ()) { 32 | callback() 33 | } 34 | #endif 35 | 36 | class PerformanceTests: XCTestCase { 37 | 38 | // GENERATED: allTests required for Swift 3.0 39 | static var allTests : [(String, (PerformanceTests) -> () throws -> Void)] { 40 | return [ 41 | ("testInitPerformance", testInitPerformance), 42 | ("testObjectMethodPerformance", testObjectMethodPerformance), 43 | ("testArrayMethodPerformance", testArrayMethodPerformance), 44 | ("testDictionaryMethodPerformance", testDictionaryMethodPerformance), 45 | ("testRawStringMethodPerformance", testRawStringMethodPerformance), 46 | ] 47 | } 48 | // END OF GENERATED CODE 49 | 50 | var testData: Data! 51 | 52 | override func setUp() { 53 | super.setUp() 54 | 55 | var testDataURL = URL(fileURLWithPath: #file) 56 | testDataURL.appendPathComponent("../Tests.json") 57 | do { 58 | self.testData = try Data(contentsOf: testDataURL.standardized) 59 | } 60 | catch { 61 | XCTFail("Failed to read in the test data") 62 | exit(1) 63 | } 64 | } 65 | 66 | override func tearDown() { 67 | // Put teardown code here. This method is called after the invocation of each test method in the class. 68 | super.tearDown() 69 | } 70 | 71 | func testInitPerformance() { 72 | self.measure() { 73 | for _ in 1...100 { 74 | let json = JSON(data:self.testData) 75 | XCTAssertTrue(json != JSON.null) 76 | } 77 | } 78 | } 79 | 80 | func testObjectMethodPerformance() { 81 | let json = JSON(data:self.testData) 82 | self.measure() { 83 | for _ in 1...100 { 84 | _ = json.object 85 | } 86 | } 87 | } 88 | 89 | func testArrayMethodPerformance() { 90 | let json = JSON(data:self.testData) 91 | self.measure() { 92 | for _ in 1...100 { 93 | autoreleasepool{ 94 | let array = json.array 95 | XCTAssertTrue( (array?.count ?? 0) > 0) 96 | } 97 | } 98 | } 99 | } 100 | 101 | func testDictionaryMethodPerformance() { 102 | let json = JSON(data:testData)[0] 103 | self.measure() { 104 | for _ in 1...100 { 105 | autoreleasepool{ 106 | let dictionary = json.dictionary 107 | XCTAssertTrue( (dictionary?.count ?? 0) > 0) 108 | } 109 | } 110 | } 111 | } 112 | 113 | func testRawStringMethodPerformance() { 114 | let json = JSON(data:testData) 115 | self.measure() { 116 | for _ in 1...100 { 117 | autoreleasepool{ 118 | let string = json.rawString() 119 | XCTAssertTrue(string != nil) 120 | } 121 | } 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/PrintableTests.swift: -------------------------------------------------------------------------------- 1 | // PrintableTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class PrintableTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (PrintableTests) -> () throws -> Void)] { 32 | return [ 33 | ("testNumber", testNumber), 34 | ("testBool", testBool), 35 | ("testString", testString), 36 | ("testNil", testNil), 37 | ("testArray", testArray), 38 | ("testDictionary", testDictionary), 39 | ] 40 | } 41 | // END OF GENERATED CODE 42 | func testNumber() { 43 | let json:JSON = 1234567890.876623 44 | // Number of fraction digits differs on OSX and Linux, 45 | // issue https://github.com/IBM-Swift/SwiftRuntime/issues/183 46 | #if (os(Linux) && !swift(>=4.2)) 47 | XCTAssertEqual(json.description, "1234567890.87662") 48 | XCTAssertEqual(json.debugDescription, "1234567890.87662") 49 | #else 50 | XCTAssertEqual(json.description, "1234567890.876623") 51 | XCTAssertEqual(json.debugDescription, "1234567890.876623") 52 | #endif 53 | } 54 | 55 | func testBool() { 56 | let jsonTrue:JSON = true 57 | XCTAssertEqual(jsonTrue.description, "true") 58 | XCTAssertEqual(jsonTrue.debugDescription, "true") 59 | let jsonFalse:JSON = false 60 | XCTAssertEqual(jsonFalse.description, "false") 61 | XCTAssertEqual(jsonFalse.debugDescription, "false") 62 | } 63 | 64 | func testString() { 65 | let json:JSON = "abcd efg, HIJK;LMn" 66 | XCTAssertEqual(json.description, "abcd efg, HIJK;LMn") 67 | XCTAssertEqual(json.debugDescription, "abcd efg, HIJK;LMn") 68 | } 69 | 70 | func testNil() { 71 | let jsonNil_1:JSON = nil 72 | XCTAssertEqual(jsonNil_1.description, "null") 73 | XCTAssertEqual(jsonNil_1.debugDescription, "null") 74 | let jsonNil_2:JSON = JSON(NSNull()) 75 | XCTAssertEqual(jsonNil_2.description, "null") 76 | XCTAssertEqual(jsonNil_2.debugDescription, "null") 77 | } 78 | 79 | func testArray() { 80 | let json:JSON = [1,2,"4",5,"6"] 81 | var description = json.description.replacingOccurrences(of: "\n", with: "") 82 | description = description.replacingOccurrences(of: " ", with: "") 83 | XCTAssertEqual(description, "[1,2,\"4\",5,\"6\"]") 84 | XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) 85 | XCTAssertTrue(json.debugDescription.lengthOfBytes(using: String.Encoding.utf8) > 0) 86 | } 87 | 88 | func testDictionary() { 89 | let json:JSON = ["1":2,"2":"two", "3":3] 90 | var debugDescription = json.debugDescription.replacingOccurrences(of: "\n", with: "") 91 | debugDescription = debugDescription.replacingOccurrences(of: " ", with: "") 92 | XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) 93 | XCTAssertTrue(debugDescription.range(of: "\"1\":2", options: .caseInsensitive) != nil) 94 | XCTAssertTrue(debugDescription.range(of: "\"2\":\"two\"", options: .caseInsensitive) != nil) 95 | XCTAssertTrue(debugDescription.range(of:"\"3\":3", options: .caseInsensitive) != nil) 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/RawRepresentableTests.swift: -------------------------------------------------------------------------------- 1 | // RawRepresentableTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class RawRepresentableTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (RawRepresentableTests) -> () throws -> Void)] { 32 | return [ 33 | ("testNumber", testNumber), 34 | ("testBool", testBool), 35 | ("testString", testString), 36 | ("testNil", testNil), 37 | ] 38 | } 39 | // END OF GENERATED CODE 40 | 41 | func testNumber() { 42 | let json:JSON = JSON(rawValue: 948394394.347384 as NSNumber)! 43 | XCTAssertEqual(json.int!, 948394394) 44 | XCTAssertEqual(json.intValue, 948394394) 45 | XCTAssertEqual(json.double!, 948394394.347384) 46 | XCTAssertEqual(json.doubleValue, 948394394.347384) 47 | XCTAssertTrue(json.float! == 948394394.347384) 48 | XCTAssertTrue(json.floatValue == 948394394.347384) 49 | 50 | let object = json.rawValue 51 | 52 | #if !os(Linux) 53 | // NSNumber to Int, Double and Float conversion doesn't work on Linux 54 | XCTAssertEqual((object as! NSNumber).intValue, 948394394) 55 | XCTAssertEqual(object as? Double, 948394394.347384) 56 | XCTAssertEqual((object as! NSNumber).floatValue, 948394394.347384) 57 | #endif 58 | XCTAssertEqual(object as? NSNumber, 948394394.347384) 59 | } 60 | 61 | func testBool() { 62 | let jsonTrue:JSON = JSON(rawValue: true as NSNumber)! 63 | 64 | // Blocked by https://bugs.swift.org/browse/SR-5803 65 | #if !(os(Linux) && swift(>=3.2)) 66 | XCTAssertEqual(jsonTrue.bool, true) 67 | #endif 68 | 69 | XCTAssertEqual(jsonTrue.boolValue, true) 70 | 71 | let jsonFalse:JSON = JSON(rawValue: false)! 72 | XCTAssertEqual(jsonFalse.bool!, false) 73 | XCTAssertEqual(jsonFalse.boolValue, false) 74 | 75 | let objectTrue = jsonTrue.rawValue 76 | 77 | // Blocked by https://bugs.swift.org/browse/SR-5803 78 | #if !(os(Linux) && swift(>=3.2)) 79 | XCTAssertEqual(objectTrue as? Bool, true) 80 | #endif 81 | 82 | #if !os(Linux) 83 | // Bool to NSNumber conversion doesn't work on Linux 84 | XCTAssertEqual(objectTrue as? NSNumber, NSNumber(value: true)) 85 | #endif 86 | 87 | let objectFalse = jsonFalse.rawValue 88 | XCTAssertEqual(objectFalse as? Bool, false) 89 | 90 | #if !os(Linux) 91 | // Bool to NSNumber conversion doesn't work on Linux 92 | XCTAssertEqual(objectFalse as? NSNumber, NSNumber(value: false)) 93 | #endif 94 | } 95 | 96 | func testString() { 97 | let string = "The better way to deal with JSON data in Swift." 98 | if let json = JSON(rawValue: string as Any) { 99 | XCTAssertEqual(json.string!, string) 100 | XCTAssertEqual(json.stringValue, string) 101 | XCTAssertTrue(json.array == nil) 102 | XCTAssertTrue(json.dictionary == nil) 103 | XCTAssertTrue(json.null == nil) 104 | XCTAssertTrue(json.error == nil) 105 | XCTAssertTrue(json.type == .string) 106 | XCTAssertEqual(json.object as? String, string) 107 | } else { 108 | XCTFail("Should not run into here") 109 | } 110 | 111 | let object = JSON(rawValue: string as Any)!.rawValue 112 | XCTAssertEqual(object as? String, string) 113 | } 114 | 115 | func testNil() { 116 | if let _ = JSON(rawValue: NSObject()) { 117 | XCTFail("Should not run into here") 118 | } 119 | } 120 | 121 | #if !os(Linux) 122 | // the following tests are not relevant to Linux 123 | // you cannot convert array/dictionary of value types to NSArray/NSDictionary 124 | func testArray() { 125 | let array = [1,2,"3",4102,"5632", "abocde", "!@# $%^&*()"] as NSArray 126 | if let json:JSON = JSON(rawValue: array) { 127 | XCTAssertEqual(json, JSON(array)) 128 | } 129 | 130 | let object = JSON(rawValue: array)!.rawValue 131 | XCTAssertTrue(array == object as! NSArray) 132 | } 133 | 134 | func testDictionary() { 135 | let dictionary = ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]] as NSDictionary 136 | if let json:JSON = JSON(rawValue: dictionary) { 137 | XCTAssertEqual(json, JSON(dictionary)) 138 | } 139 | 140 | let object = JSON(rawValue: dictionary)!.rawValue 141 | XCTAssertTrue(dictionary == object as! NSDictionary) 142 | } 143 | #endif 144 | } 145 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/RawTests.swift: -------------------------------------------------------------------------------- 1 | // RawTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class RawTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (RawTests) -> () throws -> Void)] { 32 | return [ 33 | ("testRawData", testRawData), 34 | ("testInvalidJSONForRawData", testInvalidJSONForRawData), 35 | ("testArray", testArray), 36 | ("testDictionary", testDictionary), 37 | ("testString", testString), 38 | ("testNumber", testNumber), 39 | ("testBool", testBool), 40 | ("testNull", testNull), 41 | ] 42 | } 43 | // END OF GENERATED CODE 44 | 45 | func testRawData() { 46 | let json : JSON = ["somekey" : "some string value"] 47 | let expectedRawData = "{\"somekey\":\"some string value\"}".data(using: String.Encoding.utf8) 48 | do { 49 | let data = try json.rawData() 50 | XCTAssertEqual(expectedRawData, data) 51 | } catch _ { 52 | XCTFail() 53 | } 54 | } 55 | 56 | func testInvalidJSONForRawData() { 57 | let json: JSON = "...xyz" 58 | do { 59 | _ = try json.rawData() 60 | XCTFail("rawData should throw") 61 | } catch let error as SwiftyJSONError { 62 | switch error { 63 | case .empty: 64 | XCTFail("Wrong error type") 65 | case .errorInvalidJSON(let message): 66 | XCTAssertEqual(message, "JSON is invalid") 67 | } 68 | } catch { 69 | XCTFail("Wrong error type") 70 | } 71 | } 72 | 73 | func testArray() { 74 | let json : JSON = [1, "2", 3.12, NSNull(), true, ["name": "Jack"]] 75 | 76 | let data: Data? 77 | do { 78 | data = try json.rawData() 79 | } catch _ { 80 | data = nil 81 | } 82 | let string = json.rawString() 83 | XCTAssertTrue (data != nil) 84 | XCTAssertTrue (string!.lengthOfBytes(using: String.Encoding.utf8) > 0) 85 | } 86 | 87 | func testDictionary() { 88 | let json : JSON = ["number":111111.23456789, "name":"Jack", "list":[1,2,3,4], "bool":false, "null":NSNull()] 89 | let data: Data? 90 | do { 91 | data = try json.rawData() 92 | } catch _ { 93 | data = nil 94 | } 95 | let string = json.rawString() 96 | XCTAssertTrue (data != nil) 97 | XCTAssertTrue (string!.lengthOfBytes(using: String.Encoding.utf8) > 0) 98 | } 99 | 100 | func testString() { 101 | let json:JSON = "I'm a json" 102 | XCTAssertTrue(json.rawString() == "I'm a json") 103 | } 104 | 105 | func testNumber() { 106 | let json:JSON = 123456789.123 107 | XCTAssertTrue(json.rawString() == "123456789.123") 108 | } 109 | 110 | func testBool() { 111 | let json:JSON = true 112 | XCTAssertTrue(json.rawString() == "true") 113 | } 114 | 115 | func testNull() { 116 | let json:JSON = nil 117 | XCTAssertTrue(json.rawString() == "null") 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/SequenceTypeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SequenceTypeTests.swift 3 | // 4 | // Copyright (c) 2014 Pinglin Tang 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | import XCTest 25 | import Foundation 26 | 27 | @testable import SwiftyJSON 28 | 29 | class SequenceTypeTests: XCTestCase { 30 | 31 | // GENERATED: allTests required for Swift 3.0 32 | static var allTests : [(String, (SequenceTypeTests) -> () throws -> Void)] { 33 | return [ 34 | ("testJSONFile", testJSONFile), 35 | ("testArrayAllNumber", testArrayAllNumber), 36 | ("testArrayAllBool", testArrayAllBool), 37 | ("testArrayAllString", testArrayAllString), 38 | ("testArrayWithNull", testArrayWithNull), 39 | ("testArrayAllDictionary", testArrayAllDictionary), 40 | ("testDictionaryAllNumber", testDictionaryAllNumber), 41 | ("testDictionaryAllBool", testDictionaryAllBool), 42 | ("testDictionaryAllString", testDictionaryAllString), 43 | ("testDictionaryWithNull", testDictionaryWithNull), 44 | ("testDictionaryAllArray", testDictionaryAllArray), 45 | ] 46 | } 47 | // END OF GENERATED CODE 48 | func testJSONFile() { 49 | do { 50 | var testDataURL = URL(fileURLWithPath: #file) 51 | testDataURL.appendPathComponent("../Tests.json") 52 | let testData = try Data(contentsOf: testDataURL.standardized) 53 | let json = JSON(data:testData) 54 | var ind = 0 55 | for (_, sub) in json { 56 | switch (ind) { 57 | case 0: 58 | let case0 = sub["id_str"].rawString()! 59 | XCTAssertEqual(case0, "240558470661799936") 60 | ind += 1 61 | case 1: 62 | let case1 = sub["id_str"].rawString()! 63 | XCTAssertEqual(case1, "240556426106372096") 64 | ind += 1 65 | case 2: 66 | let case2 = sub["id_str"].rawString()! 67 | XCTAssertEqual(case2, "240539141056638977") 68 | default: 69 | XCTFail("testJSONFile failed, index not found") 70 | break 71 | } 72 | } 73 | } 74 | catch { 75 | XCTFail("Failed to read in the test data") 76 | } 77 | } 78 | 79 | func testArrayAllNumber() { 80 | let json:JSON = [1,2.0,3.3,123456789,987654321.123456789] 81 | XCTAssertEqual(json.count, 5) 82 | 83 | var index = 0 84 | var array = [NSNumber]() 85 | for (i, sub) in json { 86 | XCTAssertEqual(sub, json[index]) 87 | let ind: Int? = index 88 | XCTAssertEqual(i, "\(String(describing: ind))") 89 | array.append(sub.number!) 90 | index += 1 91 | } 92 | XCTAssertEqual(index, 5) 93 | XCTAssertEqual(array, [1,2.0,3.3,123456789,987654321.123456789]) 94 | } 95 | 96 | func testArrayAllBool() { 97 | let json:JSON = JSON([true, false, false, true, true]) 98 | XCTAssertEqual(json.count, 5) 99 | 100 | var index = 0 101 | var array = [Bool]() 102 | for (i, sub) in json { 103 | XCTAssertEqual(sub, json[index]) 104 | let ind: Int? = index 105 | XCTAssertEqual(i, "\(String(describing: ind))") 106 | array.append(sub.bool!) 107 | index += 1 108 | } 109 | XCTAssertEqual(index, 5) 110 | XCTAssertEqual(array, [true, false, false, true, true]) 111 | } 112 | 113 | func testArrayAllString() { 114 | let json:JSON = JSON(rawValue: ["aoo","bpp","zoo"])! 115 | XCTAssertEqual(json.count, 3) 116 | 117 | var index = 0 118 | var array = [String]() 119 | for (i, sub) in json { 120 | XCTAssertEqual(sub, json[index]) 121 | let ind: Int? = index 122 | XCTAssertEqual(i, "\(String(describing: ind))") 123 | array.append(sub.string!) 124 | index += 1 125 | } 126 | XCTAssertEqual(index, 3) 127 | XCTAssertEqual(array, ["aoo","bpp","zoo"]) 128 | } 129 | 130 | func testArrayWithNull() { 131 | #if os(Linux) 132 | let json:JSON = JSON(rawValue: ["aoo","bpp", NSNull() ,"zoo"] as [Any?])! 133 | #else 134 | var json:JSON = JSON(rawValue: ["aoo","bpp", NSNull() ,"zoo"])! 135 | #endif 136 | XCTAssertEqual(json.count, 4) 137 | 138 | var index = 0 139 | 140 | typealias AnyType = Any //swift compiler does not like [Any]() expression 141 | var array = [AnyType]() 142 | for (i, sub) in json { 143 | XCTAssertEqual(sub, json[index]) 144 | let ind: Int? = index 145 | XCTAssertEqual(i, "\(String(describing: ind))") 146 | array.append(sub.object) 147 | index += 1 148 | } 149 | XCTAssertEqual(index, 4) 150 | XCTAssertEqual(array[0] as? String, "aoo") 151 | XCTAssertEqual(array[2] as? NSNull, NSNull()) 152 | } 153 | 154 | func testArrayAllDictionary() { 155 | let json:JSON = [["1":1, "2":2], ["a":"A", "b":"B"], ["null":NSNull()]] 156 | XCTAssertEqual(json.count, 3) 157 | 158 | var index = 0 159 | 160 | typealias AnyType = Any //swift compiler does not like [Any]() expression 161 | var array = [AnyType]() 162 | for (i, sub) in json { 163 | XCTAssertEqual(sub, json[index]) 164 | let ind: Int? = index 165 | XCTAssertEqual(i, "\(String(describing: ind))") 166 | array.append(sub.object) 167 | index += 1 168 | } 169 | XCTAssertEqual(index, 3) 170 | #if !os(Linux) 171 | // Such conversions are not supported on Linux 172 | XCTAssertEqual((array[0] as! [String : Int])["1"]!, 1) 173 | XCTAssertEqual((array[0] as! [String : Int])["2"]!, 2) 174 | XCTAssertEqual((array[1] as! [String : String])["a"]!, "A") 175 | XCTAssertEqual((array[1] as! [String : String])["b"]!, "B") 176 | XCTAssertEqual((array[2] as! [String : NSNull])["null"]!, NSNull()) 177 | #endif 178 | } 179 | 180 | func testDictionaryAllNumber() { 181 | let json:JSON = ["double":1.11111, "int":987654321] 182 | XCTAssertEqual(json.count, 2) 183 | 184 | var index = 0 185 | var dictionary = [String:NSNumber]() 186 | for (key, sub) in json { 187 | XCTAssertEqual(sub, json[key]) 188 | dictionary[key] = sub.number! 189 | index += 1 190 | } 191 | 192 | XCTAssertEqual(index, 2) 193 | XCTAssertEqual(dictionary["double"]! as NSNumber, 1.11111) 194 | XCTAssertEqual(dictionary["int"]! as NSNumber, 987654321) 195 | } 196 | 197 | func testDictionaryAllBool() { 198 | let json:JSON = ["t":true, "f":false, "false":false, "tr":true, "true":true] 199 | XCTAssertEqual(json.count, 5) 200 | 201 | var index = 0 202 | var dictionary = [String:Bool]() 203 | for (key, sub) in json { 204 | XCTAssertEqual(sub, json[key]) 205 | dictionary[key] = sub.bool! 206 | index += 1 207 | } 208 | 209 | XCTAssertEqual(index, 5) 210 | XCTAssertEqual(dictionary["t"]! as Bool, true) 211 | XCTAssertEqual(dictionary["false"]! as Bool, false) 212 | } 213 | 214 | func testDictionaryAllString() { 215 | let json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","z":"zoo"])! 216 | XCTAssertEqual(json.count, 3) 217 | 218 | var index = 0 219 | var dictionary = [String:String]() 220 | for (key, sub) in json { 221 | XCTAssertEqual(sub, json[key]) 222 | dictionary[key] = sub.string! 223 | index += 1 224 | } 225 | 226 | XCTAssertEqual(index, 3) 227 | XCTAssertEqual(dictionary["a"]! as String, "aoo") 228 | XCTAssertEqual(dictionary["bb"]! as String, "bpp") 229 | } 230 | 231 | func testDictionaryWithNull() { 232 | #if os(Linux) 233 | let json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","null":NSNull(), "z":"zoo"] as [String:Any?])! 234 | #else 235 | let json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","null":NSNull(), "z":"zoo"])! 236 | #endif 237 | XCTAssertEqual(json.count, 4) 238 | 239 | var index = 0 240 | 241 | typealias AnyType = Any //swift compiler does not like [Any]() expression 242 | var dictionary = [String: AnyType]() 243 | for (key, sub) in json { 244 | XCTAssertEqual(sub, json[key]) 245 | dictionary[key] = sub.object 246 | index += 1 247 | } 248 | 249 | XCTAssertEqual(index, 4) 250 | XCTAssertEqual(dictionary["a"]! as? String, "aoo") 251 | XCTAssertEqual(dictionary["bb"]! as? String, "bpp") 252 | XCTAssertEqual(dictionary["null"]! as? NSNull, NSNull()) 253 | } 254 | 255 | func testDictionaryAllArray() { 256 | let json:JSON = JSON (["Number":[NSNumber(value:1),NSNumber(value:2.123456),NSNumber(value:123456789)], "String":["aa","bbb","cccc"], "Mix":[true, "766", NSNull(), 655231.9823]]) 257 | 258 | XCTAssertEqual(json.count, 3) 259 | 260 | var index = 0 261 | 262 | typealias AnyType = Any //swift compiler does not like [Any]() expression 263 | var dictionary = [String: AnyType]() 264 | for (key, sub) in json { 265 | XCTAssertEqual(sub, json[key]) 266 | dictionary[key] = sub.object 267 | index += 1 268 | } 269 | 270 | XCTAssertEqual(index, 3) 271 | #if !os(Linux) 272 | // Such conversions are not supported on Linux 273 | XCTAssertEqual((dictionary["Number"] as! NSArray)[0] as? Int, 1) 274 | XCTAssertEqual((dictionary["Number"] as! NSArray)[1] as? Double, 2.123456) 275 | XCTAssertEqual((dictionary["String"] as! NSArray)[0] as? String, "aa") 276 | XCTAssertEqual((dictionary["Mix"] as! NSArray)[0] as? Bool, true) 277 | XCTAssertEqual((dictionary["Mix"] as! NSArray)[1] as? String, "766") 278 | XCTAssertEqual((dictionary["Mix"] as! NSArray)[2] as? NSNull, NSNull()) 279 | XCTAssertEqual((dictionary["Mix"] as! NSArray)[3] as? Double, 655231.9823) 280 | #endif 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/StringTests.swift: -------------------------------------------------------------------------------- 1 | // StringTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class StringTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (StringTests) -> () throws -> Void)] { 32 | return [ 33 | ("testString", testString), 34 | ("testURL", testURL), 35 | ("testURLPercentEscapes", testURLPercentEscapes), 36 | ] 37 | } 38 | // END OF GENERATED CODE 39 | 40 | func testString() { 41 | //getter 42 | var json = JSON("abcdefg hijklmn;opqrst.?+_()") 43 | XCTAssertEqual(json.string!, "abcdefg hijklmn;opqrst.?+_()") 44 | XCTAssertEqual(json.stringValue, "abcdefg hijklmn;opqrst.?+_()") 45 | 46 | json.string = "12345?67890.@#" 47 | XCTAssertEqual(json.string!, "12345?67890.@#") 48 | XCTAssertEqual(json.stringValue, "12345?67890.@#") 49 | } 50 | 51 | func testURL() { 52 | let json = JSON("http://github.com") 53 | XCTAssertEqual(json.URL!, NSURL(string:"http://github.com")!) 54 | } 55 | 56 | func testURLPercentEscapes() { 57 | let emDash = "\\u2014" 58 | let urlString = "http://examble.com/unencoded" + emDash + "string" 59 | let encodedURLString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) 60 | let json = JSON(urlString as Any) 61 | XCTAssertEqual(json.URL!, NSURL(string: encodedURLString!)!, "Wrong unpacked ") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/SubscriptTests.swift: -------------------------------------------------------------------------------- 1 | // SubscriptTests.swift 2 | // 3 | // Copyright (c) 2014 Pinglin Tang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import XCTest 24 | import Foundation 25 | 26 | @testable import SwiftyJSON 27 | 28 | class SubscriptTests: XCTestCase { 29 | 30 | // GENERATED: allTests required for Swift 3.0 31 | static var allTests : [(String, (SubscriptTests) -> () throws -> Void)] { 32 | return [ 33 | ("testArrayAllNumber", testArrayAllNumber), 34 | ("testArrayAllBool", testArrayAllBool), 35 | ("testArrayAllString", testArrayAllString), 36 | ("testArrayWithNull", testArrayWithNull), 37 | ("testArrayAllDictionary", testArrayAllDictionary), 38 | ("testDictionaryAllNumber", testDictionaryAllNumber), 39 | ("testDictionaryAllBool", testDictionaryAllBool), 40 | ("testDictionaryAllString", testDictionaryAllString), 41 | ("testDictionaryWithNull", testDictionaryWithNull), 42 | ("testDictionaryAllArray", testDictionaryAllArray), 43 | ("testOutOfBounds", testOutOfBounds), 44 | ("testErrorWrongType", testErrorWrongType), 45 | ("testErrorNotExist", testErrorNotExist), 46 | ("testMultilevelGetter", testMultilevelGetter), 47 | ("testMultilevelSetter1", testMultilevelSetter1), 48 | ("testMultilevelSetter2", testMultilevelSetter2), 49 | ("testEmptyPath", testEmptyPath), 50 | ] 51 | } 52 | // END OF GENERATED CODE 53 | 54 | func testArrayAllNumber() { 55 | var json:JSON = [1,2.0,3.3,123456789,987654321.123456789] 56 | XCTAssertTrue(json == [1,2.0,3.3,123456789,987654321.123456789]) 57 | XCTAssertTrue(json[0] == 1) 58 | XCTAssertEqual(json[1].double!, 2.0) 59 | XCTAssertTrue(json[2].floatValue == 3.3) 60 | XCTAssertEqual(json[3].int!, 123456789) 61 | XCTAssertEqual(json[4].doubleValue, 987654321.123456789) 62 | 63 | json[0] = 1.9 64 | json[1] = 2.899 65 | json[2] = 3.567 66 | json[3] = 0.999 67 | json[4] = 98732 68 | 69 | XCTAssertTrue(json[0] == 1.9) 70 | XCTAssertEqual(json[1].doubleValue, 2.899) 71 | XCTAssertTrue(json[2] == 3.567) 72 | XCTAssertTrue(json[3].float! == 0.999) 73 | XCTAssertTrue(json[4].intValue == 98732) 74 | } 75 | 76 | func testArrayAllBool() { 77 | var json:JSON = [true, false, false, true, true] 78 | XCTAssertTrue(json == [true, false, false, true, true]) 79 | XCTAssertTrue(json[0] == true) 80 | XCTAssertTrue(json[1] == false) 81 | XCTAssertTrue(json[2] == false) 82 | XCTAssertTrue(json[3] == true) 83 | XCTAssertTrue(json[4] == true) 84 | 85 | json[0] = false 86 | json[4] = true 87 | XCTAssertTrue(json[0] == false) 88 | XCTAssertTrue(json[4] == true) 89 | } 90 | 91 | func testArrayAllString() { 92 | var json:JSON = JSON(rawValue: ["aoo","bpp","zoo"])! 93 | XCTAssertTrue(json == ["aoo","bpp","zoo"]) 94 | XCTAssertTrue(json[0] == "aoo") 95 | XCTAssertTrue(json[1] == "bpp") 96 | XCTAssertTrue(json[2] == "zoo") 97 | 98 | json[1] = "update" 99 | XCTAssertTrue(json[0] == "aoo") 100 | XCTAssertTrue(json[1] == "update") 101 | XCTAssertTrue(json[2] == "zoo") 102 | } 103 | 104 | func testArrayWithNull() { 105 | #if os(Linux) 106 | var json:JSON = JSON(rawValue: ["aoo","bpp", NSNull() ,"zoo"] as [Any?])! 107 | #else 108 | var json:JSON = JSON(rawValue: ["aoo","bpp", NSNull() ,"zoo"])! 109 | #endif 110 | XCTAssertTrue(json[0] == "aoo") 111 | XCTAssertTrue(json[1] == "bpp") 112 | XCTAssertNil(json[2].string) 113 | XCTAssertNotNil(json[2].null) 114 | XCTAssertTrue(json[3] == "zoo") 115 | 116 | json[2] = "update" 117 | json[3] = JSON(NSNull()) 118 | XCTAssertTrue(json[0] == "aoo") 119 | XCTAssertTrue(json[1] == "bpp") 120 | XCTAssertTrue(json[2] == "update") 121 | XCTAssertNil(json[3].string) 122 | XCTAssertNotNil(json[3].null) 123 | } 124 | 125 | func testArrayAllDictionary() { 126 | let json:JSON = [["1":1, "2":2], ["a":"A", "b":"B"], ["null":NSNull()]] 127 | XCTAssertTrue(json[0] == ["1":1, "2":2]) 128 | XCTAssertEqual(json[1].dictionary!, ["a":"A", "b":"B"]) 129 | XCTAssertEqual(json[2], JSON(["null":NSNull()])) 130 | XCTAssertTrue(json[0]["1"] == 1) 131 | XCTAssertTrue(json[0]["2"] == 2) 132 | XCTAssertEqual(json[1]["a"], JSON(rawValue: "A")!) 133 | XCTAssertEqual(json[1]["b"], JSON("B")) 134 | XCTAssertNotNil(json[2]["null"].null) 135 | XCTAssertNotNil(json[2,"null"].null) 136 | let keys:[JSONSubscriptType] = [1, "a"] 137 | XCTAssertEqual(json[keys], JSON(rawValue: "A")!) 138 | } 139 | 140 | func testDictionaryAllNumber() { 141 | var json:JSON = ["double":1.11111, "int":987654321] 142 | XCTAssertEqual(json["double"].double!, 1.11111) 143 | XCTAssertTrue(json["int"] == 987654321) 144 | 145 | json["double"] = 2.2222 146 | json["int"] = 123456789 147 | json["add"] = 7890 148 | XCTAssertTrue(json["double"] == 2.2222) 149 | XCTAssertEqual(json["int"].doubleValue, 123456789.0) 150 | XCTAssertEqual(json["add"].intValue, 7890) 151 | } 152 | 153 | func testDictionaryAllBool() { 154 | var json:JSON = ["t":true, "f":false, "false":false, "tr":true, "true":true] 155 | XCTAssertTrue(json["t"] == true) 156 | XCTAssertTrue(json["f"] == false) 157 | XCTAssertTrue(json["false"] == false) 158 | XCTAssertTrue(json["tr"] == true) 159 | XCTAssertTrue(json["true"] == true) 160 | 161 | json["f"] = true 162 | json["tr"] = false 163 | XCTAssertTrue(json["f"] == true) 164 | XCTAssertTrue(json["tr"] == JSON(false)) 165 | } 166 | 167 | func testDictionaryAllString() { 168 | var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","z":"zoo"])! 169 | XCTAssertTrue(json["a"] == "aoo") 170 | XCTAssertEqual(json["bb"], JSON("bpp")) 171 | XCTAssertTrue(json["z"] == "zoo") 172 | 173 | json["bb"] = "update" 174 | XCTAssertTrue(json["a"] == "aoo") 175 | XCTAssertTrue(json["bb"] == "update") 176 | XCTAssertTrue(json["z"] == "zoo") 177 | } 178 | 179 | func testDictionaryWithNull() { 180 | #if os(Linux) 181 | var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","null":NSNull(), "z":"zoo"] as [String:Any?])! 182 | #else 183 | var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","null":NSNull(), "z":"zoo"])! 184 | #endif 185 | XCTAssertTrue(json["a"] == "aoo") 186 | XCTAssertEqual(json["bb"], JSON("bpp")) 187 | XCTAssertEqual(json["null"], JSON(NSNull())) 188 | XCTAssertTrue(json["z"] == "zoo") 189 | 190 | json["null"] = "update" 191 | XCTAssertTrue(json["a"] == "aoo") 192 | XCTAssertTrue(json["null"] == "update") 193 | XCTAssertTrue(json["z"] == "zoo") 194 | } 195 | 196 | func testDictionaryAllArray() { 197 | //Swift bug: [1, 2.01,3.09] is convert to [1, 2, 3] (Array) 198 | let json:JSON = JSON ([[NSNumber(value:1),NSNumber(value:2.123456),NSNumber(value:123456789)], ["aa","bbb","cccc"], [true, "766", NSNull(), 655231.9823]]) 199 | XCTAssertTrue(json[0] == [1,2.123456,123456789]) 200 | XCTAssertEqual(json[0][1].double!, 2.123456) 201 | XCTAssertTrue(json[0][2] == 123456789) 202 | XCTAssertTrue(json[1][0] == "aa") 203 | XCTAssertTrue(json[1] == ["aa","bbb","cccc"]) 204 | XCTAssertTrue(json[2][0] == true) 205 | XCTAssertTrue(json[2][1] == "766") 206 | XCTAssertTrue(json[[2,1]] == "766") 207 | XCTAssertEqual(json[2][2], JSON(NSNull())) 208 | XCTAssertEqual(json[2,2], JSON(NSNull())) 209 | XCTAssertEqual(json[2][3], JSON(655231.9823)) 210 | XCTAssertEqual(json[2,3], JSON(655231.9823)) 211 | XCTAssertEqual(json[[2,3]], JSON(655231.9823)) 212 | } 213 | 214 | func testOutOfBounds() { 215 | let json:JSON = JSON ([[NSNumber(value:1),NSNumber(value:2.123456),NSNumber(value:123456789)], ["aa","bbb","cccc"], [true, "766", NSNull(), 655231.9823]]) 216 | XCTAssertEqual(json[9], JSON.null) 217 | XCTAssertEqual(json[-2].error!.code, ErrorIndexOutOfBounds) 218 | XCTAssertEqual(json[6].error!.code, ErrorIndexOutOfBounds) 219 | XCTAssertEqual(json[9][8], JSON.null) 220 | XCTAssertEqual(json[8][7].error!.code, ErrorIndexOutOfBounds) 221 | XCTAssertEqual(json[8,7].error!.code, ErrorIndexOutOfBounds) 222 | XCTAssertEqual(json[999].error!.code, ErrorIndexOutOfBounds) 223 | } 224 | 225 | func testErrorWrongType() { 226 | let json = JSON(12345) 227 | XCTAssertEqual(json[9], JSON.null) 228 | XCTAssertEqual(json[9].error!.code, ErrorWrongType) 229 | XCTAssertEqual(json[8][7].error!.code, ErrorWrongType) 230 | XCTAssertEqual(json["name"], JSON.null) 231 | XCTAssertEqual(json["name"].error!.code, ErrorWrongType) 232 | XCTAssertEqual(json[0]["name"].error!.code, ErrorWrongType) 233 | XCTAssertEqual(json["type"]["name"].error!.code, ErrorWrongType) 234 | XCTAssertEqual(json["name"][99].error!.code, ErrorWrongType) 235 | XCTAssertEqual(json[1,"Value"].error!.code, ErrorWrongType) 236 | XCTAssertEqual(json[1, 2,"Value"].error!.code, ErrorWrongType) 237 | XCTAssertEqual(json[[1, 2,"Value"]].error!.code, ErrorWrongType) 238 | } 239 | 240 | func testErrorNotExist() { 241 | let json:JSON = ["name":"NAME", "age":15] 242 | XCTAssertEqual(json["Type"], JSON.null) 243 | XCTAssertEqual(json["Type"].error!.code, ErrorNotExist) 244 | XCTAssertEqual(json["Type"][1].error!.code, ErrorNotExist) 245 | XCTAssertEqual(json["Type", 1].error!.code, ErrorNotExist) 246 | XCTAssertEqual(json["Type"]["Value"].error!.code, ErrorNotExist) 247 | XCTAssertEqual(json["Type","Value"].error!.code, ErrorNotExist) 248 | } 249 | 250 | func testMultilevelGetter() { 251 | let json:JSON = [[[[["one":1]]]]] 252 | XCTAssertEqual(json[[0, 0, 0, 0, "one"]].int!, 1) 253 | XCTAssertEqual(json[0, 0, 0, 0, "one"].int!, 1) 254 | XCTAssertEqual(json[0][0][0][0]["one"].int!, 1) 255 | } 256 | 257 | func testMultilevelSetter1() { 258 | var json:JSON = [[[[["num":1]]]]] 259 | json[0, 0, 0, 0, "num"] = 2 260 | XCTAssertEqual(json[[0, 0, 0, 0, "num"]].intValue, 2) 261 | json[0, 0, 0, 0, "num"] = nil 262 | XCTAssertEqual(json[0, 0, 0, 0, "num"].null!, NSNull()) 263 | json[0, 0, 0, 0, "num"] = 100.009 264 | XCTAssertEqual(json[0][0][0][0]["num"].doubleValue, 100.009) 265 | json[[0, 0, 0, 0]] = ["name":"Jack"] 266 | XCTAssertEqual(json[0,0,0,0,"name"].stringValue, "Jack") 267 | XCTAssertEqual(json[0][0][0][0]["name"].stringValue, "Jack") 268 | XCTAssertEqual(json[[0,0,0,0,"name"]].stringValue, "Jack") 269 | json[[0,0,0,0,"name"]].string = "Mike" 270 | XCTAssertEqual(json[0,0,0,0,"name"].stringValue, "Mike") 271 | let path:[JSONSubscriptType] = [0,0,0,0,"name"] 272 | json[path].string = "Jim" 273 | XCTAssertEqual(json[path].stringValue, "Jim") 274 | } 275 | 276 | func testMultilevelSetter2() { 277 | var json:JSON = ["user":["id":987654, "info":["name":"jack","email":"jack@gmail.com"], "feeds":[98833,23443,213239,23232]] as [String:Any]] 278 | json["user","info","name"] = "jim" 279 | XCTAssertEqual(json["user","id"], 987654) 280 | XCTAssertEqual(json["user","info","name"], "jim") 281 | XCTAssertEqual(json["user","info","email"], "jack@gmail.com") 282 | XCTAssertEqual(json["user","feeds"], [98833,23443,213239,23232]) 283 | json["user","info","email"] = "jim@hotmail.com" 284 | XCTAssertEqual(json["user","id"], 987654) 285 | XCTAssertEqual(json["user","info","name"], "jim") 286 | XCTAssertEqual(json["user","info","email"], "jim@hotmail.com") 287 | XCTAssertEqual(json["user","feeds"], [98833,23443,213239,23232]) 288 | json["user","info"] = ["name":"tom","email":"tom@qq.com"] 289 | XCTAssertEqual(json["user","id"], 987654) 290 | XCTAssertEqual(json["user","info","name"], "tom") 291 | XCTAssertEqual(json["user","info","email"], "tom@qq.com") 292 | XCTAssertEqual(json["user","feeds"], [98833,23443,213239,23232]) 293 | json["user","feeds"] = [77323,2313,4545,323] 294 | XCTAssertEqual(json["user","id"], 987654) 295 | XCTAssertEqual(json["user","info","name"], "tom") 296 | XCTAssertEqual(json["user","info","email"], "tom@qq.com") 297 | XCTAssertEqual(json["user","feeds"], [77323,2313,4545,323]) 298 | } 299 | 300 | func testEmptyPath() { 301 | var json = JSON(["number": JSON(123), "code": JSON(456)]) 302 | 303 | let emptyArray: [String] = [] 304 | let emptySubscript = emptyArray.map { $0 as JSONSubscriptType} 305 | 306 | json[emptySubscript] = JSON(7) 307 | XCTAssertEqual(json.number!, 7) 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /Tests/SwiftyJSONTests/Tests.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "coordinates":null, 4 | "truncated":false, 5 | "created_at":"Tue Aug 28 21:16:23 +0000 2012", 6 | "favorited":false, 7 | "id_str":"240558470661799936", 8 | "in_reply_to_user_id_str":null, 9 | "entities":{ 10 | "urls":[ 11 | 12 | ], 13 | "hashtags":[ 14 | 15 | ], 16 | "user_mentions":[ 17 | 18 | ] 19 | }, 20 | "text":"just another test", 21 | "contributors":null, 22 | "id":240558470661799936, 23 | "retweet_count":0, 24 | "in_reply_to_status_id_str":null, 25 | "geo":null, 26 | "retweeted":false, 27 | "in_reply_to_user_id":null, 28 | "place":null, 29 | "source":"<a href=\"//realitytechnicians.com\" rel=\"\"nofollow\"\">OAuth Dancer Reborn</a>", 30 | "user":{ 31 | "name":"OAuth Dancer", 32 | "profile_sidebar_fill_color":"DDEEF6", 33 | "profile_background_tile":true, 34 | "profile_sidebar_border_color":"C0DEED", 35 | "profile_image_url":"http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg", 36 | "created_at":"Wed Mar 03 19:37:35 +0000 2010", 37 | "location":"San Francisco, CA", 38 | "follow_request_sent":false, 39 | "id_str":"119476949", 40 | "is_translator":false, 41 | "profile_link_color":"0084B4", 42 | "entities":{ 43 | "url":{ 44 | "urls":[ 45 | { 46 | "expanded_url":null, 47 | "url":"http://bit.ly/oauth-dancer", 48 | "indices":[ 49 | 0, 50 | 26 51 | ], 52 | "display_url":null 53 | } 54 | ] 55 | }, 56 | "description":null 57 | }, 58 | "default_profile":false, 59 | "url":"http://bit.ly/oauth-dancer", 60 | "contributors_enabled":false, 61 | "favourites_count":7, 62 | "utc_offset":null, 63 | "profile_image_url_https":"https://si0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg", 64 | "id":119476949, 65 | "listed_count":1, 66 | "profile_use_background_image":true, 67 | "profile_text_color":"333333", 68 | "followers_count":28, 69 | "lang":"en", 70 | "protected":false, 71 | "geo_enabled":true, 72 | "notifications":false, 73 | "description":"", 74 | "profile_background_color":"C0DEED", 75 | "verified":false, 76 | "time_zone":null, 77 | "profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/80151733/oauth-dance.png", 78 | "statuses_count":166, 79 | "profile_background_image_url":"http://a0.twimg.com/profile_background_images/80151733/oauth-dance.png", 80 | "default_profile_image":false, 81 | "friends_count":14, 82 | "following":false, 83 | "show_all_inline_media":false, 84 | "screen_name":"oauth_dancer" 85 | }, 86 | "in_reply_to_screen_name":null, 87 | "in_reply_to_status_id":null 88 | }, 89 | { 90 | "coordinates":{ 91 | "coordinates":[ 92 | -122.25831, 93 | 37.871609 94 | ], 95 | "type":"Point" 96 | }, 97 | "truncated":false, 98 | "created_at":"Tue Aug 28 21:08:15 +0000 2012", 99 | "favorited":false, 100 | "id_str":"240556426106372096", 101 | "in_reply_to_user_id_str":null, 102 | "entities":{ 103 | "urls":[ 104 | { 105 | "expanded_url":"http://blogs.ischool.berkeley.edu/i290-abdt-s12/", 106 | "url":"http://t.co/bfj7zkDJ", 107 | "indices":[ 108 | 79, 109 | 99 110 | ], 111 | "display_url":"blogs.ischool.berkeley.edu/i290-abdt-s12/" 112 | } 113 | ], 114 | "hashtags":[ 115 | 116 | ], 117 | "user_mentions":[ 118 | { 119 | "name":"Cal", 120 | "id_str":"17445752", 121 | "id":17445752, 122 | "indices":[ 123 | 60, 124 | 64 125 | ], 126 | "screen_name":"Cal" 127 | }, 128 | { 129 | "name":"Othman Laraki", 130 | "id_str":"20495814", 131 | "id":20495814, 132 | "indices":[ 133 | 70, 134 | 77 135 | ], 136 | "screen_name":"othman" 137 | } 138 | ] 139 | }, 140 | "text":"lecturing at the \"analyzing big data with twitter\" class at @cal with @othman http://t.co/bfj7zkDJ", 141 | "contributors":null, 142 | "id":240556426106372096, 143 | "retweet_count":3, 144 | "in_reply_to_status_id_str":null, 145 | "geo":{ 146 | "coordinates":[ 147 | 37.871609, 148 | -122.25831 149 | ], 150 | "type":"Point" 151 | }, 152 | "retweeted":false, 153 | "possibly_sensitive":false, 154 | "in_reply_to_user_id":null, 155 | "place":{ 156 | "name":"Berkeley", 157 | "country_code":"US", 158 | "country":"United States", 159 | "attributes":{ 160 | 161 | }, 162 | "url":"http://api.twitter.com/1/geo/id/5ef5b7f391e30aff.json", 163 | "id":"5ef5b7f391e30aff", 164 | "bounding_box":{ 165 | "coordinates":[ 166 | [ 167 | [ 168 | -122.367781, 169 | 37.835727 170 | ], 171 | [ 172 | -122.234185, 173 | 37.835727 174 | ], 175 | [ 176 | -122.234185, 177 | 37.905824 178 | ], 179 | [ 180 | -122.367781, 181 | 37.905824 182 | ] 183 | ] 184 | ], 185 | "type":"Polygon" 186 | }, 187 | "full_name":"Berkeley, CA", 188 | "place_type":"city" 189 | }, 190 | "source":"<a href=\"//www.apple.com\"\" rel=\"\"nofollow\"\">Safari on iOS</a>", 191 | "user":{ 192 | "name":"Raffi Krikorian", 193 | "profile_sidebar_fill_color":"DDEEF6", 194 | "profile_background_tile":false, 195 | "profile_sidebar_border_color":"C0DEED", 196 | "profile_image_url":"http://a0.twimg.com/profile_images/1270234259/raffi-headshot-casual_normal.png", 197 | "created_at":"Sun Aug 19 14:24:06 +0000 2007", 198 | "location":"San Francisco, California", 199 | "follow_request_sent":false, 200 | "id_str":"8285392", 201 | "is_translator":false, 202 | "profile_link_color":"0084B4", 203 | "entities":{ 204 | "url":{ 205 | "urls":[ 206 | { 207 | "expanded_url":"http://about.me/raffi.krikorian", 208 | "url":"http://t.co/eNmnM6q", 209 | "indices":[ 210 | 0, 211 | 19 212 | ], 213 | "display_url":"about.me/raffi.krikorian" 214 | } 215 | ] 216 | }, 217 | "description":{ 218 | "urls":[ 219 | 220 | ] 221 | } 222 | }, 223 | "default_profile":true, 224 | "url":"http://t.co/eNmnM6q", 225 | "contributors_enabled":false, 226 | "favourites_count":724, 227 | "utc_offset":-28800, 228 | "profile_image_url_https":"https://si0.twimg.com/profile_images/1270234259/raffi-headshot-casual_normal.png", 229 | "id":8285392, 230 | "listed_count":619, 231 | "profile_use_background_image":true, 232 | "profile_text_color":"333333", 233 | "followers_count":18752, 234 | "lang":"en", 235 | "protected":false, 236 | "geo_enabled":true, 237 | "notifications":false, 238 | "description":"Director of @twittereng's Platform Services. I break things.", 239 | "profile_background_color":"C0DEED", 240 | "verified":false, 241 | "time_zone":"Pacific Time (US & Canada)", 242 | "profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png", 243 | "statuses_count":5007, 244 | "profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png", 245 | "default_profile_image":false, 246 | "friends_count":701, 247 | "following":true, 248 | "show_all_inline_media":true, 249 | "screen_name":"raffi" 250 | }, 251 | "in_reply_to_screen_name":null, 252 | "in_reply_to_status_id":null 253 | }, 254 | { 255 | "coordinates":null, 256 | "truncated":false, 257 | "created_at":"Tue Aug 28 19:59:34 +0000 2012", 258 | "favorited":false, 259 | "id_str":"240539141056638977", 260 | "in_reply_to_user_id_str":null, 261 | "entities":{ 262 | "urls":[ 263 | 264 | ], 265 | "hashtags":[ 266 | 267 | ], 268 | "user_mentions":[ 269 | 270 | ] 271 | }, 272 | "text":"You'd be right more often if you thought you were wrong.", 273 | "contributors":null, 274 | "id":240539141056638977, 275 | "retweet_count":1, 276 | "in_reply_to_status_id_str":null, 277 | "geo":null, 278 | "retweeted":false, 279 | "in_reply_to_user_id":null, 280 | "place":null, 281 | "source":"web", 282 | "user":{ 283 | "name":"Taylor Singletary", 284 | "profile_sidebar_fill_color":"FBFBFB", 285 | "profile_background_tile":true, 286 | "profile_sidebar_border_color":"000000", 287 | "profile_image_url":"http://a0.twimg.com/profile_images/2546730059/f6a8zq58mg1hn0ha8vie_normal.jpeg", 288 | "created_at":"Wed Mar 07 22:23:19 +0000 2007", 289 | "location":"San Francisco, CA", 290 | "follow_request_sent":false, 291 | "id_str":"819797", 292 | "is_translator":false, 293 | "profile_link_color":"c71818", 294 | "entities":{ 295 | "url":{ 296 | "urls":[ 297 | { 298 | "expanded_url":"http://www.rebelmouse.com/episod/", 299 | "url":"http://t.co/Lxw7upbN", 300 | "indices":[ 301 | 0, 302 | 20 303 | ], 304 | "display_url":"rebelmouse.com/episod/" 305 | } 306 | ] 307 | }, 308 | "description":{ 309 | "urls":[ 310 | 311 | ] 312 | } 313 | }, 314 | "default_profile":false, 315 | "url":"http://t.co/Lxw7upbN", 316 | "contributors_enabled":false, 317 | "favourites_count":15990, 318 | "utc_offset":-28800, 319 | "profile_image_url_https":"https://si0.twimg.com/profile_images/2546730059/f6a8zq58mg1hn0ha8vie_normal.jpeg", 320 | "id":819797, 321 | "listed_count":340, 322 | "profile_use_background_image":true, 323 | "profile_text_color":"D20909", 324 | "followers_count":7126, 325 | "lang":"en", 326 | "protected":false, 327 | "geo_enabled":true, 328 | "notifications":false, 329 | "description":"Reality Technician, Twitter API team, synthesizer enthusiast; a most excellent adventure in timelines. I know it's hard to believe in something you can't see.", 330 | "profile_background_color":"000000", 331 | "verified":false, 332 | "time_zone":"Pacific Time (US & Canada)", 333 | "profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/643655842/hzfv12wini4q60zzrthg.png", 334 | "statuses_count":18076, 335 | "profile_background_image_url":"http://a0.twimg.com/profile_background_images/643655842/hzfv12wini4q60zzrthg.png", 336 | "default_profile_image":false, 337 | "friends_count":5444, 338 | "following":true, 339 | "show_all_inline_media":true, 340 | "screen_name":"episod" 341 | }, 342 | "in_reply_to_screen_name":null, 343 | "in_reply_to_status_id":null 344 | } 345 | ] --------------------------------------------------------------------------------