diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 00000000..eb2ba192 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,33 @@ +### What did you do? + +Please replace this with what you did. + +### What did you expect to happen? + +Please replace this with what you expected to happen. + +### What actually happened instead? + +Please replace this with what happened instead. + +### Environment + +List the software versions you're using: + + - SwiftyJSON: *?.?.?* + - Xcode Version: *?.? (????)* (Open Xcode; In menubar: Xcode > About Xcode) + - Swift Version: *?.?* (Open Xcode Preferences; Components > Toolchains. If none, use `Xcode Default`.) + +Please also mention which package manager you used and its version. Delete the +other package managers in this list: + + - Cocoapods: *?.?.?* (Use `pod --version` in Terminal) + - Carthage: *?.?* (Use `carthage version` in Terminal) + - Swift Package Manager *?.?.? (swiftpm-???)* (Use `swift build --version` in Terminal) + +### Project that demonstrates the issue + +Please link to a project we can download that reproduces the issue. Feel free +to delete this section if it's not relevant to the issue (eg - feature request). + +The project should be [short, self-contained, and correct example](http://sscce.org/). \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 00000000..5efff141 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,13 @@ +The PR should summarize what was changed and why. Here are some questions to +help you if you're not sure: + + - What behavior was changed? + - What code was refactored / updated to support this change? + - What issues are related to this PR? Or why was this change introduced? + +Checklist - While not every PR needs it, new features should consider this list: + + - [ ] Does this have tests? + - [ ] Does this have documentation? + - [ ] Does this break the public API (Requires major version bump)? + - [ ] Is this a new feature (Requires minor version bump)? \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..ba72e725 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: CI + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + build-and-test: + runs-on: macos-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build + run: xcrun swift build --build-tests + + - name: Run tests + run: xcrun swift test \ No newline at end of file diff --git a/.hound.yml b/.hound.yml new file mode 100644 index 00000000..b867fd9c --- /dev/null +++ b/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/.swift-version b/.swift-version deleted file mode 100644 index 9f55b2cc..00000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -3.0 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 00000000..36ee05ac --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,10 @@ +disabled_rules: + - force_cast + - force_try + - identifier_name + - type_name + - file_length + - line_length + - type_body_length + - cyclomatic_complexity + - function_body_length diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 63840195..00000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: objective-c -osx_image: xcode8 -xcode_sdk: iphonesimulator10.0 -env: - global: - - FRAMEWORK_NAME=SwiftyJSON -before_install: -- rvm get head -- brew update -- brew outdated carthage || brew upgrade carthage -before_deploy: -- carthage build --no-skip-current -- carthage archive $FRAMEWORK_NAME -script: -- set -o pipefail -- travis_retry xcodebuild -workspace SwiftyJSON.xcworkspace -scheme "SwiftyJSON iOS" -destination "platform=iOS Simulator,name=iPhone 6" build-for-testing test | xcpretty -- travis_retry xcodebuild -workspace SwiftyJSON.xcworkspace -scheme "SwiftyJSON OSX" build-for-testing test | xcpretty -- travis_retry xcodebuild -workspace SwiftyJSON.xcworkspace -scheme "SwiftyJSON tvOS" -destination "platform=tvOS Simulator,name=Apple TV 1080p" build-for-testing test | xcpretty -deploy: - provider: releases - api_key: - secure: MufQRIzcHPU5fn9gyXl7kDGaLihN6zGABx9UWqNtkwq0AxV0aYNWys11nrKDIgoZFR+MbQHMoodpZK03yDdCLG03ncnOr3aytLOpI0imuDFWx16sieiVoYmnP5bfNFTN0qqXdfBy0OOsx4wO+F5Pwg5y1TgGYnKpXtEfdIU3Om4= - file: SwiftyJSON.framework.zip - skip_cleanup: true - on: - repo: SwiftyJSON/SwiftyJSON - tags: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a0935d3..082b0247 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ [Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.2.0...HEAD) +### Added +- Swift 6 support with full Sendable conformance ([#1163](https://github.com/SwiftyJSON/SwiftyJSON/issues/1163)) +- Comprehensive concurrency tests for actor boundary validation + +### Changed +- `JSON` struct conforms to `@unchecked Sendable` +- `Type`, `SwiftyJSONError`, `JSONKey` enums conform to `Sendable` +- Minimum Swift tools version updated to 6.0 + **Closed issues:** - 156 compiler errors Mavericks + Xcode 6.2 [\#220](https://github.com/SwiftyJSON/SwiftyJSON/issues/220) diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index b114ac1e..e0a5e55e 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -32,7 +32,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 04294C501BE5A9DE00D0397E /* Playground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground.playground; sourceTree = ""; }; + 04294C501BE5A9DE00D0397E /* Playground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 04733F511D92E6ED002E3A99 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A82A1C1919D926B8009A653D /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; A82A1C1D19D926B8009A653D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -124,19 +124,19 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = swiftyjson; TargetAttributes = { A82A1C1819D926B8009A653D = { CreatedOnToolsVersion = 6.0.1; - LastSwiftMigration = 0820; + LastSwiftMigration = 1020; ProvisioningStyle = Manual; }; }; }; buildConfigurationList = A82A1C1419D926B8009A653D /* Build configuration list for PBXProject "Example" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -206,14 +206,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -254,14 +262,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -297,7 +313,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -312,7 +328,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Example/Example/AppDelegate.swift b/Example/Example/AppDelegate.swift index 6c0aead8..c4236b1d 100644 --- a/Example/Example/AppDelegate.swift +++ b/Example/Example/AppDelegate.swift @@ -1,4 +1,4 @@ -// SwiftyJSON.h +// AppDelegate.swift // // Copyright (c) 2014 - 2016 Pinglin Tang // @@ -28,15 +28,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + let navigationController = self.window?.rootViewController as! UINavigationController let viewController = navigationController.topViewController as! ViewController - + if let file = Bundle.main.path(forResource: "SwiftyJSONTests", ofType: "json") { do { let data = try Data(contentsOf: URL(fileURLWithPath: file)) - let json = JSON(data: data) + let json = try JSON(data: data) viewController.json = json } catch { viewController.json = JSON.null @@ -44,8 +44,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } else { viewController.json = JSON.null } - + return true } } - diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index db1d1da1..8f297a7b 100644 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -1,4 +1,4 @@ -// SwiftyJSON.h +// ViewController.swift // // Copyright (c) 2014 - 2016 Pinglin Tang // @@ -26,16 +26,16 @@ import SwiftyJSON class ViewController: UITableViewController { var json: JSON = JSON.null - + // MARK: - Table view data source - override func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } + override func viewDidLoad() { + title = "SwiftyJSON(\(json.type))" + } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch self.json.type { - case Type.array, Type.dictionary: + case .array, .dictionary: return self.json.count default: return 1 @@ -44,9 +44,9 @@ class ViewController: UITableViewController { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "JSONCell", for: indexPath) as UITableViewCell - - let row = (indexPath as NSIndexPath).row - + + let row = indexPath.row + switch self.json.type { case .array: cell.textLabel?.text = "\(row)" @@ -60,7 +60,7 @@ class ViewController: UITableViewController { cell.textLabel?.text = "" cell.detailTextLabel?.text = self.json.description } - + return cell } @@ -70,9 +70,9 @@ class ViewController: UITableViewController { var nextController: UIViewController? nextController = segue.destination - + if let indexPath = self.tableView.indexPathForSelectedRow { - let row = (indexPath as NSIndexPath).row + let row = indexPath.row var nextJson: JSON = JSON.null switch self.json.type { case .array: diff --git a/Example/Playground.playground/Contents.swift b/Example/Playground.playground/Contents.swift index 90b99433..7542d181 100644 --- a/Example/Playground.playground/Contents.swift +++ b/Example/Playground.playground/Contents.swift @@ -1,98 +1,414 @@ //: Playground - noun: a place where people can play /*: - # SwiftyJSON - SwiftyJSON makes it easy to deal with JSON data in Swift. - - You must have to build `SwiftyJSON iOS` package for import. - */ -/*: - ### Basic setting for playground - */ +# SwiftyJSON +SwiftyJSON makes it easy to deal with JSON data in Swift. + +You must have to build `SwiftyJSON iOS` package for import. +*/ +/*: +### Basic setting for playground +*/ import SwiftyJSON import Foundation var jsonData: Data? if let file = Bundle.main.path(forResource: "SwiftyJSONTests", ofType: "json") { - jsonData = try? Data(contentsOf: URL(fileURLWithPath: file)) + jsonData = try? Data(contentsOf: URL(fileURLWithPath: file)) } else { - print("Fail") + print("Fail") } -let jsonObject = try JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments) as? [[String: AnyObject]] +let jsonObject = try JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments) let jsonString = String(data: jsonData!, encoding: .utf8) /*: - ## Usage - - ### Initialization - - */ -import SwiftyJSON +## Usage + +### Initialization -let json1 = JSON(data: jsonData!) +*/ + +let json1 = try? JSON(data: jsonData!) /*: - or - */ +or +*/ let json2 = JSON(jsonObject) /*: - or - */ +or +*/ let dataFromString = jsonString?.data(using: .utf8) -let json3 = JSON(data: dataFromString!) +let json3 = try? JSON(data: dataFromString!) /*: - ### Subscript - */ +### Subscript +*/ // Example json -var jsonArray: JSON = [ - "array": [12.34, 56.78], - "users": [ - [ - "id": 987654, - "info": [ - "name": "jack", - "email": "jack@gmail.com" - ], - "feeds": [98833, 23443, 213239, 23232] - ], - [ - "id": 654321, - "info": [ - "name": "jeffgukang", - "email": "jeffgukang@gmail.com" - ], - "feeds": [12345, 56789, 12423, 12412] - ] - ] -] - -var jsonDictionary: JSON = [ - "name": "jeffgukang", - "country": "South Korea" -] +let json: JSON = JSON([ + "array": [12.34, 56.78], + "users": [ + [ + "id": 987654, + "info": [ + "name": "jack", + "email": "jack@gmail.com" + ], + "feeds": [98833, 23443, 213239, 23232] + ], + [ + "id": 654321, + "info": [ + "name": "jeffgukang", + "email": "jeffgukang@gmail.com" + ], + "feeds": [12345, 56789, 12423, 12412] + ] + ] + ]) // Getting a double from a JSON Array -jsonArray["array"][0].double +json["array"][0].double // Getting an array of string from a JSON Array -let arrayOfString = jsonArray["users"].arrayValue.map({$0["info"]["name"]}) +let arrayOfString = json["users"].arrayValue.map({$0["info"]["name"]}) print(arrayOfString) // Getting a string from a JSON Dictionary -jsonDictionary["country"].stringValue +json["users"][0]["info"]["name"].stringValue -//Getting a string using a path to the element +// Getting a string using a path to the element let path = ["users", 1, "info", "name"] as [JSONSubscriptType] -var name = jsonArray["users",1,"info","name"].string +var name = json["users", 1, "info", "name"].string -//With a custom way +// With a custom way let keys: [JSONSubscriptType] = ["users", 1, "info", "name"] -name = jsonArray[keys].string +name = json[keys].string + +// Just the same +name = json["users"][1]["info"]["name"].string + +// Alternatively +name = json["users", 1, "info", "name"].string + +/*: +### Loop +*/ +// If json is .Dictionary +for (key, subJson):(String, JSON) in json { + //Do something you want + print(key) + print(subJson) +} + +/*The first element is always a String, even if the JSON is an Array*/ +//If json is .Array +//The `index` is 0.. For Legacy Swift support, take a look at the [swift2 branch](https://github.com/SwiftyJSON/SwiftyJSON/tree/swift2) - -> [中文介绍](http://tangplin.github.io/swiftyjson/) +6. [Work with Moya](#work-with-moya) +7. [SwiftyJSON Model Generator](#swiftyjson-model-generator) ## Why is the typical JSON handling in Swift NOT good? 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. -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). +Take the Twitter API for example. Say we want to retrieve a user's "name" value of some tweet in Swift (according to [Twitter's API](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline)). The code would look like this: @@ -57,7 +58,7 @@ An unreadable mess--for something that should really be simple! With SwiftyJSON all you have to do is: ```swift -let json = JSON(data: dataFromNetworking) +let json = try? JSON(data: dataFromNetworking) if let userName = json[0]["user"]["name"].string { //Now you got your value } @@ -66,63 +67,63 @@ if let userName = json[0]["user"]["name"].string { And don't worry about the Optional Wrapping thing. It's done for you automatically. ```swift -let json = JSON(data: dataFromNetworking) -if let userName = json[999999]["wrong_key"]["wrong_name"].string { +let json = try? JSON(data: dataFromNetworking) +let result = json[999999]["wrong_key"]["wrong_name"] +if let userName = result.string { //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety } else { //Print the error - print(json[999999]["wrong_key"]["wrong_name"]) + print(result.error) } ``` ## Requirements - iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+ -- Xcode 8 +- Xcode 16+ +- Swift 6.0+ ## Integration #### CocoaPods (iOS 8+, OS X 10.9+) -You can use [CocoaPods](http://cocoapods.org/) to install `SwiftyJSON`by adding it to your `Podfile`: +You can use [CocoaPods](http://cocoapods.org/) to install `SwiftyJSON` by adding it to your `Podfile`: ```ruby platform :ios, '8.0' use_frameworks! target 'MyApp' do - pod 'SwiftyJSON' + pod 'SwiftyJSON', '~> 4.0' end ``` -Note that this requires CocoaPods version 36, and your iOS deployment target to be at least 8.0: - - #### Carthage (iOS 8+, OS X 10.9+) You can use [Carthage](https://github.com/Carthage/Carthage) to install `SwiftyJSON` by adding it to your `Cartfile`: ``` -github "SwiftyJSON/SwiftyJSON" +github "SwiftyJSON/SwiftyJSON" ~> 4.0 ``` +If you use Carthage to build your dependencies, make sure you have added `SwiftyJSON.framework` to the "Linked Frameworks and Libraries" section of your target, and have included them in your Carthage framework copying build phase. + #### Swift Package Manager 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: ```swift +// swift-tools-version:4.0 import PackageDescription let package = Package( name: "YOUR_PROJECT_NAME", - targets: [], dependencies: [ - .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", versions: Version(1,0,0).. = json["list"].arrayValue ``` ```swift -//If not a Dictionary or nil, return [:] +// If not a Dictionary or nil, return [:] let user: Dictionary = json["user"].dictionaryValue ``` @@ -341,31 +351,36 @@ json.dictionaryObject = ["name":"Jack", "age":25] #### Raw object ```swift -let jsonObject: Any = json.object +let rawObject: Any = json.object ``` ```swift -if let jsonObject: Any = json.rawValue +let rawValue: Any = json.rawValue ``` ```swift //convert the JSON to raw NSData -if let data = json.rawData() { - //Do something you want +do { + let rawData = try json.rawData() + //Do something you want +} catch { + print("Error \(error)") } ``` ```swift //convert the JSON to a raw String -if let string = json.rawString() { - //Do something you want +if let rawString = json.rawString() { + //Do something you want +} else { + print("json.rawString is nil") } ``` #### Existence ```swift -//shows you whether value specified in JSON or not +// shows you whether value specified in JSON or not if json["name"].exists() ``` @@ -374,59 +389,54 @@ if json["name"].exists() For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/) ```swift -//StringLiteralConvertible +// StringLiteralConvertible let json: JSON = "I'm a json" ``` ```swift -//IntegerLiteralConvertible +// IntegerLiteralConvertible let json: JSON = 12345 ``` ```swift -//BooleanLiteralConvertible +// BooleanLiteralConvertible let json: JSON = true ``` ```swift -//FloatLiteralConvertible +// FloatLiteralConvertible let json: JSON = 2.8765 ``` ```swift -//DictionaryLiteralConvertible +// DictionaryLiteralConvertible let json: JSON = ["I":"am", "a":"json"] ``` ```swift -//ArrayLiteralConvertible +// ArrayLiteralConvertible let json: JSON = ["I", "am", "a", "json"] ``` ```swift -//NilLiteralConvertible -let json: JSON = nil -``` - -```swift -//With subscript in array +// With subscript in array var json: JSON = [1,2,3] json[0] = 100 json[1] = 200 json[2] = 300 -json[999] = 300 //Don't worry, nothing will happen +json[999] = 300 // Don't worry, nothing will happen ``` ```swift -//With subscript in dictionary +// With subscript in dictionary var json: JSON = ["name": "Jack", "age": 25] json["name"] = "Mike" -json["age"] = "25" //It's OK to set String +json["age"] = "25" // It's OK to set String json["address"] = "L.A." // Add the "address": "L.A." in json ``` ```swift -//Array & Dictionary +// Array & Dictionary var json: JSON = ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]] json["list"][3]["what"] = "that" json["list",3,"what"] = "that" @@ -435,10 +445,10 @@ json[path] = "that" ``` ```swift -//With other JSON objects +// With other JSON objects let user: JSON = ["username" : "Steve", "password": "supersecurepassword"] let auth: JSON = [ - "user": user.object //use user.object instead of just user + "user": user.object, // use user.object instead of just user "apikey": "supersecretapitoken" ] ``` @@ -449,10 +459,10 @@ It is possible to merge one JSON into another JSON. Merging a JSON into another If both JSONs contain a value for the same key, _mostly_ this value gets overwritten in the original JSON, but there are two cases where it provides some special treatment: -- In case of both values being a `JSON.Type.array` the values form the array found in the `other` JSON getting appended to the original JSON's array value. +- In case of both values being a `JSON.Type.array` the values form the array found in the `other` JSON getting appended to the original JSON's array value. - In case of both values being a `JSON.Type.dictionary` both JSON-values are getting merged the same way the encapsulating JSON is merged. -In case, where two fields in a JSON have a different types, the value will get always overwritten. +In a case where two fields in a JSON have different types, the value will get always overwritten. There are two different fashions for merging: `merge` modifies the original JSON, whereas `merged` works non-destructively on a copy. @@ -491,6 +501,69 @@ let updated = original.merge(with: update) // ] ``` + +#### Removing elements + +If you are storing dictionaries, you can remove elements using `dictionaryObject.removeValue(forKey:)`. This mutates the JSON object in place. + +For example: + +```swift +var object = JSON([ + "one": ["color": "blue"], + "two": ["city": "tokyo", + "country": "japan", + "foods": [ + "breakfast": "tea", + "lunch": "sushi" + ] + ] +]) +``` + +Lets remove the `country` key: + +```swift +object["two"].dictionaryObject?.removeValue(forKey: "country") +``` + +If you `print(object)`, you'll see that the `country` key no longer exists. + +```json +{ + "one" : { + "color" : "blue" + }, + "two" : { + "city" : "tokyo", + "foods" : { + "breakfast" : "tea", + "lunch" : "sushi" + } + } +} +``` + +This also works for nested dictionaries: + +```swift +object["two"]["foods"].dictionaryObject?.removeValue(forKey: "breakfast") +``` + +```json +{ + "one" : { + "color" : "blue" + }, + "two" : { + "city" : "tokyo", + "foods" : { + "lunch" : "sushi" + } + } +} +``` + ## String representation There are two options available: - use the default Swift one @@ -502,7 +575,7 @@ let representation = json.rawString(options: [.castNilToNSNull: true]) // representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null} ``` -## Work with Alamofire +## Work with [Alamofire](https://github.com/Alamofire/Alamofire) SwiftyJSON nicely wraps the result of the Alamofire JSON response handler: @@ -517,3 +590,31 @@ Alamofire.request(url, method: .get).validate().responseJSON { response in } } ``` + +We also provide an extension of Alamofire for serializing NSData to SwiftyJSON's JSON. + +See: [Alamofire-SwiftyJSON](https://github.com/SwiftyJSON/Alamofire-SwiftyJSON) + + +## Work with [Moya](https://github.com/Moya/Moya) + +SwiftyJSON parse data to JSON: + +```swift +let provider = MoyaProvider() +provider.request(.showProducts) { result in + switch result { + case let .success(moyaResponse): + let data = moyaResponse.data + let json = JSON(data: data) // convert network data to json + print(json) + case let .failure(error): + print("error: \(error)") + } +} + +``` + +## SwiftyJSON Model Generator +Tools to generate SwiftyJSON Models +* [JSON Export](https://github.com/Ahmed-Ali/JSONExport) diff --git a/Source/Info-OSX.plist b/Source/Info-macOS.plist similarity index 100% rename from Source/Info-OSX.plist rename to Source/Info-macOS.plist diff --git a/Source/SwiftyJSON.swift b/Source/SwiftyJSON.swift deleted file mode 100644 index 14a1e60c..00000000 --- a/Source/SwiftyJSON.swift +++ /dev/null @@ -1,1485 +0,0 @@ -// SwiftyJSON.swift -// -// Copyright (c) 2014 - 2017 Ruoyu Fu, Pinglin Tang -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -// MARK: - Error - -///Error domain -public let ErrorDomain: String = "SwiftyJSONErrorDomain" - -///Error code -public let ErrorUnsupportedType: Int = 999 -public let ErrorIndexOutOfBounds: Int = 900 -public let ErrorWrongType: Int = 901 -public let ErrorNotExist: Int = 500 -public let ErrorInvalidJSON: Int = 490 - -// MARK: - JSON Type - -/** - JSON's type definitions. - - See http://www.json.org - */ -public enum Type :Int{ - - case number - case string - case bool - case array - case dictionary - case null - case unknown -} - -// MARK: - JSON Base -public struct JSON { - - /** - Creates a JSON using the data. - - - parameter data: The NSData used to convert to json.Top level object in data is an NSArray or NSDictionary - - parameter opt: The JSON serialization reading options. `.AllowFragments` by default. - - parameter error: The NSErrorPointer used to return the error. `nil` by default. - - - returns: The created JSON - */ - public init(data: Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer = nil) { - do { - let object: Any = try JSONSerialization.jsonObject(with: data, options: opt) - self.init(jsonObject: object) - } catch let aError as NSError { - if error != nil { - error?.pointee = aError - } - self.init(jsonObject: NSNull()) - } - } - - /** - Creates a JSON object - - parameter object: the object - - note: this does not parse a `String` into JSON, instead use `init(parseJSON: String)` - - returns: the created JSON object - */ - public init(_ object: Any) { - switch object { - case let object as [JSON] where object.count > 0: - self.init(array: object) - case let object as [String: JSON] where object.count > 0: - self.init(dictionary: object) - case let object as Data: - self.init(data: object) - default: - self.init(jsonObject: object) - } - } - - /** - Parses the JSON string into a JSON object - - parameter json: the JSON string - - returns: the created JSON object - */ - public init(parseJSON jsonString: String) { - if let data = jsonString.data(using: .utf8) { - self.init(data) - } else { - self.init(NSNull()) - } - } - - /** - Creates a JSON from JSON string - - parameter string: Normal json string like '{"a":"b"}' - - - returns: The created JSON - */ - @available(*, deprecated: 3.2, message: "Use instead `init(parseJSON: )`") - public static func parse(_ json: String) -> JSON { - return json.data(using: String.Encoding.utf8) - .flatMap{ JSON(data: $0) } ?? JSON(NSNull()) - } - - /** - Creates a JSON using the object. - - - 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. - - - returns: The created JSON - */ - fileprivate init(jsonObject: Any) { - self.object = jsonObject - } - - /** - Creates a JSON from a [JSON] - - - parameter jsonArray: A Swift array of JSON objects - - - returns: The created JSON - */ - fileprivate init(array: [JSON]) { - self.init(array.map { $0.object }) - } - - /** - Creates a JSON from a [String: JSON] - - - parameter jsonDictionary: A Swift dictionary of JSON objects - - - returns: The created JSON - */ - fileprivate init(dictionary: [String: JSON]) { - var newDictionary = [String: Any](minimumCapacity: dictionary.count) - for (key, json) in dictionary { - newDictionary[key] = json.object - } - - self.init(newDictionary) - } - - /** - Merges another JSON into this JSON, whereas primitive values which are not present in this JSON are getting added, - present values getting overwritten, array values getting appended and nested JSONs getting merged the same way. - - - parameter other: The JSON which gets merged into this JSON - - throws `ErrorWrongType` if the other JSONs differs in type on the top level. - */ - public mutating func merge(with other: JSON) throws { - try self.merge(with: other, typecheck: true) - } - - /** - Merges another JSON into this JSON and returns a new JSON, whereas primitive values which are not present in this JSON are getting added, - present values getting overwritten, array values getting appended and nested JSONS getting merged the same way. - - - parameter other: The JSON which gets merged into this JSON - - returns: New merged JSON - - throws `ErrorWrongType` if the other JSONs differs in type on the top level. - */ - public func merged(with other: JSON) throws -> JSON { - var merged = self - try merged.merge(with: other, typecheck: true) - return merged - } - - // Private woker function which does the actual merging - // Typecheck is set to true for the first recursion level to prevent total override of the source JSON - fileprivate mutating func merge(with other: JSON, typecheck: Bool) throws { - if self.type == other.type { - switch self.type { - case .dictionary: - for (key, _) in other { - try self[key].merge(with: other[key], typecheck: false) - } - case .array: - self = JSON(self.arrayValue + other.arrayValue) - default: - self = other - } - } else { - if typecheck { - throw NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Couldn't merge, because the JSONs differ in type on top level."]) - } else { - self = other - } - } - } - - /// Private object - fileprivate var rawArray: [Any] = [] - fileprivate var rawDictionary: [String : Any] = [:] - fileprivate var rawString: String = "" - fileprivate var rawNumber: NSNumber = 0 - fileprivate var rawNull: NSNull = NSNull() - fileprivate var rawBool: Bool = false - /// Private type - fileprivate var _type: Type = .null - /// prviate error - fileprivate var _error: NSError? = nil - - /// Object in JSON - public var object: Any { - get { - switch self.type { - case .array: - return self.rawArray - case .dictionary: - return self.rawDictionary - case .string: - return self.rawString - case .number: - return self.rawNumber - case .bool: - return self.rawBool - default: - return self.rawNull - } - } - set { - _error = nil - switch newValue { - case let number as NSNumber: - if number.isBool { - _type = .bool - self.rawBool = number.boolValue - } else { - _type = .number - self.rawNumber = number - } - case let string as String: - _type = .string - self.rawString = string - case _ as NSNull: - _type = .null - case _ as [JSON]: - _type = .array - case nil: - _type = .null - case let array as [Any]: - _type = .array - self.rawArray = array - case let dictionary as [String : Any]: - _type = .dictionary - self.rawDictionary = dictionary - default: - _type = .unknown - _error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"]) - } - } - } - - /// JSON type - public var type: Type { get { return _type } } - - /// Error in JSON - public var error: NSError? { get { return self._error } } - - /// The static null JSON - @available(*, unavailable, renamed:"null") - public static var nullJSON: JSON { get { return null } } - public static var null: JSON { get { return JSON(NSNull()) } } -} - -public enum Index: Comparable -{ - case array(Int) - case dictionary(DictionaryIndex) - case null - - static public func ==(lhs: Index, rhs: Index) -> Bool { - switch (lhs, rhs) { - case (.array(let left), .array(let right)): - return left == right - case (.dictionary(let left), .dictionary(let right)): - return left == right - case (.null, .null): return true - default: - return false - } - } - - static public func <(lhs: Index, rhs: Index) -> Bool { - switch (lhs, rhs) { - case (.array(let left), .array(let right)): - return left < right - case (.dictionary(let left), .dictionary(let right)): - return left < right - default: - return false - } - } -} - -public typealias JSONIndex = Index -public typealias JSONRawIndex = Index - - -extension JSON: Collection -{ - - public typealias Index = JSONRawIndex - - public var startIndex: Index - { - switch type - { - case .array: - return .array(rawArray.startIndex) - case .dictionary: - return .dictionary(rawDictionary.startIndex) - default: - return .null - } - } - - public var endIndex: Index - { - switch type - { - case .array: - return .array(rawArray.endIndex) - case .dictionary: - return .dictionary(rawDictionary.endIndex) - default: - return .null - } - } - - public func index(after i: Index) -> Index - { - switch i - { - case .array(let idx): - return .array(rawArray.index(after: idx)) - case .dictionary(let idx): - return .dictionary(rawDictionary.index(after: idx)) - default: - return .null - } - - } - - public subscript (position: Index) -> (String, JSON) - { - switch position - { - case .array(let idx): - return (String(idx), JSON(self.rawArray[idx])) - case .dictionary(let idx): - let (key, value) = self.rawDictionary[idx] - return (key, JSON(value)) - default: - return ("", JSON.null) - } - } - - -} - -// MARK: - Subscript - -/** - * To mark both String and Int can be used in subscript. - */ -public enum JSONKey -{ - case index(Int) - case key(String) -} - -public protocol JSONSubscriptType { - var jsonKey:JSONKey { get } -} - -extension Int: JSONSubscriptType { - public var jsonKey:JSONKey { - return JSONKey.index(self) - } -} - -extension String: JSONSubscriptType { - public var jsonKey:JSONKey { - return JSONKey.key(self) - } -} - -extension JSON { - - /// If `type` is `.Array`, return json whose object is `array[index]`, otherwise return null json with error. - fileprivate subscript(index index: Int) -> JSON { - get { - if self.type != .array { - var r = JSON.null - r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] failure, It is not an array"]) - return r - } else if index >= 0 && index < self.rawArray.count { - return JSON(self.rawArray[index]) - } else { - var r = JSON.null - r._error = NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds , userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] is out of bounds"]) - return r - } - } - set { - if self.type == .array { - if self.rawArray.count > index && newValue.error == nil { - self.rawArray[index] = newValue.object - } - } - } - } - - /// If `type` is `.Dictionary`, return json whose object is `dictionary[key]` , otherwise return null json with error. - fileprivate subscript(key key: String) -> JSON { - get { - var r = JSON.null - if self.type == .dictionary { - if let o = self.rawDictionary[key] { - r = JSON(o) - } else { - r._error = NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] does not exist"]) - } - } else { - r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] failure, It is not an dictionary"]) - } - return r - } - set { - if self.type == .dictionary && newValue.error == nil { - self.rawDictionary[key] = newValue.object - } - } - } - - /// If `sub` is `Int`, return `subscript(index:)`; If `sub` is `String`, return `subscript(key:)`. - fileprivate subscript(sub sub: JSONSubscriptType) -> JSON { - get { - switch sub.jsonKey { - case .index(let index): return self[index: index] - case .key(let key): return self[key: key] - } - } - set { - switch sub.jsonKey { - case .index(let index): self[index: index] = newValue - case .key(let key): self[key: key] = newValue - } - } - } - - /** - Find a json in the complex data structures by using array of Int and/or String as path. - - - parameter path: The target json's path. Example: - - let json = JSON[data] - let path = [9,"list","person","name"] - let name = json[path] - - The same as: let name = json[9]["list"]["person"]["name"] - - - returns: Return a json found by the path or a null json with error - */ - public subscript(path: [JSONSubscriptType]) -> JSON { - get { - return path.reduce(self) { $0[sub: $1] } - } - set { - switch path.count { - case 0: - return - case 1: - self[sub:path[0]].object = newValue.object - default: - var aPath = path; aPath.remove(at: 0) - var nextJSON = self[sub: path[0]] - nextJSON[aPath] = newValue - self[sub: path[0]] = nextJSON - } - } - } - - /** - Find a json in the complex data structures by using array of Int and/or String as path. - - - parameter path: The target json's path. Example: - - let name = json[9,"list","person","name"] - - The same as: let name = json[9]["list"]["person"]["name"] - - - returns: Return a json found by the path or a null json with error - */ - public subscript(path: JSONSubscriptType...) -> JSON { - get { - return self[path] - } - set { - self[path] = newValue - } - } -} - -// MARK: - LiteralConvertible - -extension JSON: Swift.ExpressibleByStringLiteral { - - public init(stringLiteral value: StringLiteralType) { - self.init(value as Any) - } - - public init(extendedGraphemeClusterLiteral value: StringLiteralType) { - self.init(value as Any) - } - - public init(unicodeScalarLiteral value: StringLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByIntegerLiteral { - - public init(integerLiteral value: IntegerLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByBooleanLiteral { - - public init(booleanLiteral value: BooleanLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByFloatLiteral { - - public init(floatLiteral value: FloatLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByDictionaryLiteral { - public init(dictionaryLiteral elements: (String, Any)...) { - let array = elements - self.init(dictionaryLiteral: array) - } - - public init(dictionaryLiteral elements: [(String, Any)]) { - let jsonFromDictionaryLiteral: ([String : Any]) -> JSON = { dictionary in - let initializeElement = Array(dictionary.keys).flatMap { key -> (String, Any)? in - if let value = dictionary[key] { - return (key, value) - } - return nil - } - return JSON(dictionaryLiteral: initializeElement) - } - - var dict = [String : Any](minimumCapacity: elements.count) - - for element in elements { - let elementToSet: Any - if let json = element.1 as? JSON { - elementToSet = json.object - } else if let jsonArray = element.1 as? [JSON] { - elementToSet = JSON(jsonArray).object - } else if let dictionary = element.1 as? [String : Any] { - elementToSet = jsonFromDictionaryLiteral(dictionary).object - } else if let dictArray = element.1 as? [[String : Any]] { - let jsonArray = dictArray.map { jsonFromDictionaryLiteral($0) } - elementToSet = JSON(jsonArray).object - } else { - elementToSet = element.1 - } - dict[element.0] = elementToSet - } - - self.init(dict) - } -} - -extension JSON: Swift.ExpressibleByArrayLiteral { - - public init(arrayLiteral elements: Any...) { - self.init(elements as Any) - } -} - -extension JSON: Swift.ExpressibleByNilLiteral { - - @available(*, deprecated, message: "use JSON.null instead. Will be removed in future versions") - public init(nilLiteral: ()) { - self.init(NSNull() as Any) - } -} - -// MARK: - Raw - -extension JSON: Swift.RawRepresentable { - - public init?(rawValue: Any) { - if JSON(rawValue).type == .unknown { - return nil - } else { - self.init(rawValue) - } - } - - public var rawValue: Any { - return self.object - } - - public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data { - guard JSONSerialization.isValidJSONObject(self.object) else { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "JSON is invalid"]) - } - - return try JSONSerialization.data(withJSONObject: self.object, options: opt) - } - - public func rawString(_ encoding: String.Encoding = .utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? { - do { - return try _rawString(encoding, options: [.jsonSerialization: opt]) - } catch { - print("Could not serialize object to JSON because:", error.localizedDescription) - return nil - } - } - - public func rawString(_ options: [writingOptionsKeys: Any]) -> String? { - let encoding = options[.encoding] as? String.Encoding ?? String.Encoding.utf8 - let maxObjectDepth = options[.maxObjextDepth] as? Int ?? 10 - do { - return try _rawString(encoding, options: options, maxObjectDepth: maxObjectDepth) - } catch { - print("Could not serialize object to JSON because:", error.localizedDescription) - return nil - } - } - - fileprivate func _rawString( - _ encoding: String.Encoding = .utf8, - options: [writingOptionsKeys: Any], - maxObjectDepth: Int = 10 - ) throws -> String? { - if (maxObjectDepth < 0) { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "Element too deep. Increase maxObjectDepth and make sure there is no reference loop"]) - } - switch self.type { - case .dictionary: - do { - if !(options[.castNilToNSNull] as? Bool ?? false) { - let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted - let data = try self.rawData(options: jsonOption) - return String(data: data, encoding: encoding) - } - - guard let dict = self.object as? [String: Any?] else { - return nil - } - let body = try dict.keys.map { key throws -> String in - guard let value = dict[key] else { - return "\"\(key)\": null" - } - guard let unwrappedValue = value else { - return "\"\(key)\": null" - } - - let nestedValue = JSON(unwrappedValue) - guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "Could not serialize nested JSON"]) - } - if nestedValue.type == .string { - return "\"\(key)\": \"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\"" - } else { - return "\"\(key)\": \(nestedString)" - } - } - - return "{\(body.joined(separator: ","))}" - } catch _ { - return nil - } - case .array: - do { - if !(options[.castNilToNSNull] as? Bool ?? false) { - let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted - let data = try self.rawData(options: jsonOption) - return String(data: data, encoding: encoding) - } - - guard let array = self.object as? [Any?] else { - return nil - } - let body = try array.map { value throws -> String in - guard let unwrappedValue = value else { - return "null" - } - - let nestedValue = JSON(unwrappedValue) - guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "Could not serialize nested JSON"]) - } - if nestedValue.type == .string { - return "\"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\"" - } else { - return nestedString - } - } - - return "[\(body.joined(separator: ","))]" - } catch _ { - return nil - } - case .string: - return self.rawString - case .number: - return self.rawNumber.stringValue - case .bool: - return self.rawBool.description - case .null: - return "null" - default: - return nil - } - } -} - -// MARK: - Printable, DebugPrintable - -extension JSON: Swift.CustomStringConvertible, Swift.CustomDebugStringConvertible { - - public var description: String { - if let string = self.rawString(options:.prettyPrinted) { - return string - } else { - return "unknown" - } - } - - public var debugDescription: String { - return description - } -} - -// MARK: - Array - -extension JSON { - - //Optional [JSON] - public var array: [JSON]? { - get { - if self.type == .array { - return self.rawArray.map{ JSON($0) } - } else { - return nil - } - } - } - - //Non-optional [JSON] - public var arrayValue: [JSON] { - get { - return self.array ?? [] - } - } - - //Optional [Any] - public var arrayObject: [Any]? { - get { - switch self.type { - case .array: - return self.rawArray - default: - return nil - } - } - set { - if let array = newValue { - self.object = array as Any - } else { - self.object = NSNull() - } - } - } -} - -// MARK: - Dictionary - -extension JSON { - - //Optional [String : JSON] - public var dictionary: [String : JSON]? { - if self.type == .dictionary { - var d = [String : JSON](minimumCapacity: rawDictionary.count) - for (key, value) in rawDictionary { - d[key] = JSON(value) - } - return d - } else { - return nil - } - } - - //Non-optional [String : JSON] - public var dictionaryValue: [String : JSON] { - return self.dictionary ?? [:] - } - - //Optional [String : Any] - - public var dictionaryObject: [String : Any]? { - get { - switch self.type { - case .dictionary: - return self.rawDictionary - default: - return nil - } - } - set { - if let v = newValue { - self.object = v as Any - } else { - self.object = NSNull() - } - } - } -} - -// MARK: - Bool - -extension JSON { // : Swift.Bool - - //Optional bool - public var bool: Bool? { - get { - switch self.type { - case .bool: - return self.rawBool - default: - return nil - } - } - set { - if let newValue = newValue { - self.object = newValue as Bool - } else { - self.object = NSNull() - } - } - } - - //Non-optional bool - public var boolValue: Bool { - get { - switch self.type { - case .bool: - return self.rawBool - case .number: - return self.rawNumber.boolValue - case .string: - return ["true", "y", "t"].contains() { (truthyString) in - return self.rawString.caseInsensitiveCompare(truthyString) == .orderedSame - } - default: - return false - } - } - set { - self.object = newValue - } - } -} - -// MARK: - String - -extension JSON { - - //Optional string - public var string: String? { - get { - switch self.type { - case .string: - return self.object as? String - default: - return nil - } - } - set { - if let newValue = newValue { - self.object = NSString(string:newValue) - } else { - self.object = NSNull() - } - } - } - - //Non-optional string - public var stringValue: String { - get { - switch self.type { - case .string: - return self.object as? String ?? "" - case .number: - return self.rawNumber.stringValue - case .bool: - return (self.object as? Bool).map { String($0) } ?? "" - default: - return "" - } - } - set { - self.object = NSString(string:newValue) - } - } -} - -// MARK: - Number -extension JSON { - - //Optional number - public var number: NSNumber? { - get { - switch self.type { - case .number: - return self.rawNumber - case .bool: - return NSNumber(value: self.rawBool ? 1 : 0) - default: - return nil - } - } - set { - self.object = newValue ?? NSNull() - } - } - - //Non-optional number - public var numberValue: NSNumber { - get { - switch self.type { - case .string: - let decimal = NSDecimalNumber(string: self.object as? String) - if decimal == NSDecimalNumber.notANumber { // indicates parse error - return NSDecimalNumber.zero - } - return decimal - case .number: - return self.object as? NSNumber ?? NSNumber(value: 0) - case .bool: - return NSNumber(value: self.rawBool ? 1 : 0) - default: - return NSNumber(value: 0.0) - } - } - set { - self.object = newValue - } - } -} - -//MARK: - Null -extension JSON { - - public var null: NSNull? { - get { - switch self.type { - case .null: - return self.rawNull - default: - return nil - } - } - set { - self.object = NSNull() - } - } - public func exists() -> Bool{ - if let errorValue = error, errorValue.code == ErrorNotExist || - errorValue.code == ErrorIndexOutOfBounds || - errorValue.code == ErrorWrongType { - return false - } - return true - } -} - -//MARK: - URL -extension JSON { - - //Optional URL - public var url: URL? { - get { - switch self.type { - case .string: - // Check for existing percent escapes first to prevent double-escaping of % character - if let _ = self.rawString.range(of: "%[0-9A-Fa-f]{2}", options: .regularExpression, range: nil, locale: nil) { - return Foundation.URL(string: self.rawString) - } else if let encodedString_ = self.rawString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) { - // We have to use `Foundation.URL` otherwise it conflicts with the variable name. - return Foundation.URL(string: encodedString_) - } else { - return nil - } - default: - return nil - } - } - set { - self.object = newValue?.absoluteString ?? NSNull() - } - } -} - -// MARK: - Int, Double, Float, Int8, Int16, Int32, Int64 - -extension JSON { - - public var double: Double? { - get { - return self.number?.doubleValue - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var doubleValue: Double { - get { - return self.numberValue.doubleValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var float: Float? { - get { - return self.number?.floatValue - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var floatValue: Float { - get { - return self.numberValue.floatValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int: Int? - { - get - { - return self.number?.intValue - } - set - { - if let newValue = newValue - { - self.object = NSNumber(value: newValue) - } else - { - self.object = NSNull() - } - } - } - - public var intValue: Int { - get { - return self.numberValue.intValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt: UInt? { - get { - return self.number?.uintValue - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uIntValue: UInt { - get { - return self.numberValue.uintValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int8: Int8? { - get { - return self.number?.int8Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: Int(newValue)) - } else { - self.object = NSNull() - } - } - } - - public var int8Value: Int8 { - get { - return self.numberValue.int8Value - } - set { - self.object = NSNumber(value: Int(newValue)) - } - } - - public var uInt8: UInt8? { - get { - return self.number?.uint8Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt8Value: UInt8 { - get { - return self.numberValue.uint8Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int16: Int16? { - get { - return self.number?.int16Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var int16Value: Int16 { - get { - return self.numberValue.int16Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt16: UInt16? { - get { - return self.number?.uint16Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt16Value: UInt16 { - get { - return self.numberValue.uint16Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int32: Int32? { - get { - return self.number?.int32Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var int32Value: Int32 { - get { - return self.numberValue.int32Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt32: UInt32? { - get { - return self.number?.uint32Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt32Value: UInt32 { - get { - return self.numberValue.uint32Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int64: Int64? { - get { - return self.number?.int64Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var int64Value: Int64 { - get { - return self.numberValue.int64Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt64: UInt64? { - get { - return self.number?.uint64Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt64Value: UInt64 { - get { - return self.numberValue.uint64Value - } - set { - self.object = NSNumber(value: newValue) - } - } -} - -//MARK: - Comparable -extension JSON : Swift.Comparable {} - -public func ==(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber == rhs.rawNumber - case (.string, .string): - return lhs.rawString == rhs.rawString - case (.bool, .bool): - return lhs.rawBool == rhs.rawBool - case (.array, .array): - return lhs.rawArray as NSArray == rhs.rawArray as NSArray - case (.dictionary, .dictionary): - return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary - case (.null, .null): - return true - default: - return false - } -} - -public func <=(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber <= rhs.rawNumber - case (.string, .string): - return lhs.rawString <= rhs.rawString - case (.bool, .bool): - return lhs.rawBool == rhs.rawBool - case (.array, .array): - return lhs.rawArray as NSArray == rhs.rawArray as NSArray - case (.dictionary, .dictionary): - return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary - case (.null, .null): - return true - default: - return false - } -} - -public func >=(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber >= rhs.rawNumber - case (.string, .string): - return lhs.rawString >= rhs.rawString - case (.bool, .bool): - return lhs.rawBool == rhs.rawBool - case (.array, .array): - return lhs.rawArray as NSArray == rhs.rawArray as NSArray - case (.dictionary, .dictionary): - return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary - case (.null, .null): - return true - default: - return false - } -} - -public func >(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber > rhs.rawNumber - case (.string, .string): - return lhs.rawString > rhs.rawString - default: - return false - } -} - -public func <(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber < rhs.rawNumber - case (.string, .string): - return lhs.rawString < rhs.rawString - default: - return false - } -} - -private let trueNumber = NSNumber(value: true) -private let falseNumber = NSNumber(value: false) -private let trueObjCType = String(cString: trueNumber.objCType) -private let falseObjCType = String(cString: falseNumber.objCType) - -// MARK: - NSNumber: Comparable - -extension NSNumber { - var isBool:Bool { - get { - let objCType = String(cString: self.objCType) - if (self.compare(trueNumber) == .orderedSame && objCType == trueObjCType) || (self.compare(falseNumber) == .orderedSame && objCType == falseObjCType){ - return true - } else { - return false - } - } - } -} - -func ==(lhs: NSNumber, rhs: NSNumber) -> Bool { - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) == .orderedSame - } -} - -func !=(lhs: NSNumber, rhs: NSNumber) -> Bool { - return !(lhs == rhs) -} - -func <(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) == .orderedAscending - } -} - -func >(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) == ComparisonResult.orderedDescending - } -} - -func <=(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) != .orderedDescending - } -} - -func >=(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) != .orderedAscending - } -} - -public enum writingOptionsKeys { - case jsonSerialization - case castNilToNSNull - case maxObjextDepth - case encoding -} diff --git a/Source/SwiftyJSON/PrivacyInfo.xcprivacy b/Source/SwiftyJSON/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..d37d6275 --- /dev/null +++ b/Source/SwiftyJSON/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + NSPrivacyTrackingDomains + + NSPrivacyTracking + + + diff --git a/Source/SwiftyJSON.h b/Source/SwiftyJSON/SwiftyJSON.h similarity index 100% rename from Source/SwiftyJSON.h rename to Source/SwiftyJSON/SwiftyJSON.h diff --git a/Source/SwiftyJSON/SwiftyJSON.swift b/Source/SwiftyJSON/SwiftyJSON.swift new file mode 100644 index 00000000..d2f39ef2 --- /dev/null +++ b/Source/SwiftyJSON/SwiftyJSON.swift @@ -0,0 +1,1397 @@ +// SwiftyJSON.swift +// +// Copyright (c) 2014 - 2017 Ruoyu Fu, Pinglin Tang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +// MARK: - Error +// swiftlint:disable line_length +public enum SwiftyJSONError: Int, Swift.Error, Sendable { + case unsupportedType = 999 + case indexOutOfBounds = 900 + case elementTooDeep = 902 + case wrongType = 901 + case notExist = 500 + case invalidJSON = 490 +} + +extension SwiftyJSONError: CustomNSError { + + /// return the error domain of SwiftyJSONError + public static var errorDomain: String { return "com.swiftyjson.SwiftyJSON" } + + /// return the error code of SwiftyJSONError + public var errorCode: Int { return self.rawValue } + + /// return the userInfo of SwiftyJSONError + public var errorUserInfo: [String: Any] { + switch self { + case .unsupportedType: + return [NSLocalizedDescriptionKey: "It is an unsupported type."] + case .indexOutOfBounds: + return [NSLocalizedDescriptionKey: "Array Index is out of bounds."] + case .wrongType: + return [NSLocalizedDescriptionKey: "Couldn't merge, because the JSONs differ in type on top level."] + case .notExist: + return [NSLocalizedDescriptionKey: "Dictionary key does not exist."] + case .invalidJSON: + return [NSLocalizedDescriptionKey: "JSON is invalid."] + case .elementTooDeep: + return [NSLocalizedDescriptionKey: "Element too deep. Increase maxObjectDepth and make sure there is no reference loop."] + } + } +} + +// MARK: - JSON Type + +/** +JSON's type definitions. + +See http://www.json.org +*/ +public enum Type: Int, Sendable { + case number + case string + case bool + case array + case dictionary + case null + case unknown +} + +// MARK: - JSON Base + +public struct JSON: @unchecked Sendable { + + /** + Creates a JSON using the data. + + - parameter data: The NSData used to convert to json.Top level object in data is an NSArray or NSDictionary + - parameter opt: The JSON serialization reading options. `[]` by default. + + - returns: The created JSON + */ + public init(data: Data, options opt: JSONSerialization.ReadingOptions = []) throws { + let object: Any = try JSONSerialization.jsonObject(with: data, options: opt) + self.init(jsonObject: object) + } + + /** + Creates a JSON object + - note: this does not parse a `String` into JSON, instead use `init(parseJSON: String)` + + - parameter object: the object + + - returns: the created JSON object + */ + public init(_ object: Any) { + switch object { + case let object as Data: + do { + try self.init(data: object) + } catch { + self.init(jsonObject: NSNull()) + } + default: + self.init(jsonObject: object) + } + } + + /** + Parses the JSON string into a JSON object + + - parameter json: the JSON string + + - returns: the created JSON object + */ + public init(parseJSON jsonString: String) { + if let data = jsonString.data(using: .utf8) { + self.init(data) + } else { + self.init(NSNull()) + } + } + + /** + Creates a JSON using the object. + + - parameter jsonObject: 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. + + - returns: The created JSON + */ + fileprivate init(jsonObject: Any) { + object = jsonObject + } + + /** + Merges another JSON into this JSON, whereas primitive values which are not present in this JSON are getting added, + present values getting overwritten, array values getting appended and nested JSONs getting merged the same way. + + - parameter other: The JSON which gets merged into this JSON + + - throws `ErrorWrongType` if the other JSONs differs in type on the top level. + */ + public mutating func merge(with other: JSON) throws { + try self.merge(with: other, typecheck: true) + } + + /** + Merges another JSON into this JSON and returns a new JSON, whereas primitive values which are not present in this JSON are getting added, + present values getting overwritten, array values getting appended and nested JSONS getting merged the same way. + + - parameter other: The JSON which gets merged into this JSON + + - throws `ErrorWrongType` if the other JSONs differs in type on the top level. + + - returns: New merged JSON + */ + public func merged(with other: JSON) throws -> JSON { + var merged = self + try merged.merge(with: other, typecheck: true) + return merged + } + + /** + Private woker function which does the actual merging + Typecheck is set to true for the first recursion level to prevent total override of the source JSON + */ + fileprivate mutating func merge(with other: JSON, typecheck: Bool) throws { + if type == other.type { + switch type { + case .dictionary: + for (key, _) in other { + try self[key].merge(with: other[key], typecheck: false) + } + case .array: + self = JSON(arrayValue + other.arrayValue) + default: + self = other + } + } else { + if typecheck { + throw SwiftyJSONError.wrongType + } else { + self = other + } + } + } + + /// Private object + fileprivate var rawArray: [Any] = [] + fileprivate var rawDictionary: [String: Any] = [:] + fileprivate var rawString: String = "" + fileprivate var rawNumber: NSNumber = 0 + fileprivate var rawNull: NSNull = NSNull() + fileprivate var rawBool: Bool = false + + /// JSON type, fileprivate setter + public fileprivate(set) var type: Type = .null + + /// Error in JSON, fileprivate setter + public fileprivate(set) var error: SwiftyJSONError? + + /// Object in JSON + public var object: Any { + get { + switch type { + case .array: return rawArray + case .dictionary: return rawDictionary + case .string: return rawString + case .number: return rawNumber + case .bool: return rawBool + default: return rawNull + } + } + set { + error = nil + switch unwrap(newValue) { + case let number as NSNumber: + if number.isBool { + type = .bool + rawBool = number.boolValue + } else { + type = .number + rawNumber = number + } + case let string as String: + type = .string + rawString = string + case _ as NSNull: + type = .null + case Optional.none: + type = .null + case let array as [Any]: + type = .array + rawArray = array + case let dictionary as [String: Any]: + type = .dictionary + rawDictionary = dictionary + default: + type = .unknown + error = SwiftyJSONError.unsupportedType + } + } + } + + /// The static null JSON + @available(*, unavailable, renamed:"null") + public static var nullJSON: JSON { return null } + public static var null: JSON { return JSON(NSNull()) } +} + +/// Private method to unwarp an object recursively +private func unwrap(_ object: Any) -> Any { + switch object { + case let json as JSON: + return unwrap(json.object) + case let array as [Any]: + return array.map(unwrap) + case let dictionary as [String: Any]: + return dictionary.mapValues(unwrap) + default: + return object + } +} + +public enum Index: Comparable { + case array(Int) + case dictionary(DictionaryIndex) + case null + + static public func == (lhs: Index, rhs: Index) -> Bool { + switch (lhs, rhs) { + case (.array(let left), .array(let right)): return left == right + case (.dictionary(let left), .dictionary(let right)): return left == right + case (.null, .null): return true + default: return false + } + } + + static public func < (lhs: Index, rhs: Index) -> Bool { + switch (lhs, rhs) { + case (.array(let left), .array(let right)): return left < right + case (.dictionary(let left), .dictionary(let right)): return left < right + default: return false + } + } +} + +public typealias JSONIndex = Index +public typealias JSONRawIndex = Index + +extension JSON: Swift.Collection { + + public typealias Index = JSONRawIndex + + public var startIndex: Index { + switch type { + case .array: return .array(rawArray.startIndex) + case .dictionary: return .dictionary(rawDictionary.startIndex) + default: return .null + } + } + + public var endIndex: Index { + switch type { + case .array: return .array(rawArray.endIndex) + case .dictionary: return .dictionary(rawDictionary.endIndex) + default: return .null + } + } + + public func index(after i: Index) -> Index { + switch i { + case .array(let idx): return .array(rawArray.index(after: idx)) + case .dictionary(let idx): return .dictionary(rawDictionary.index(after: idx)) + default: return .null + } + } + + public subscript (position: Index) -> (String, JSON) { + switch position { + case .array(let idx): return (String(idx), JSON(rawArray[idx])) + case .dictionary(let idx): return (rawDictionary[idx].key, JSON(rawDictionary[idx].value)) + default: return ("", JSON.null) + } + } +} + +// MARK: - Subscript + +/** + * To mark both String and Int can be used in subscript. + */ +public enum JSONKey: Sendable { + case index(Int) + case key(String) +} + +public protocol JSONSubscriptType { + var jsonKey: JSONKey { get } +} + +extension Int: JSONSubscriptType { + public var jsonKey: JSONKey { + return JSONKey.index(self) + } +} + +extension String: JSONSubscriptType { + public var jsonKey: JSONKey { + return JSONKey.key(self) + } +} + +extension JSON { + + /// If `type` is `.array`, return json whose object is `array[index]`, otherwise return null json with error. + fileprivate subscript(index index: Int) -> JSON { + get { + if type != .array { + var r = JSON.null + r.error = self.error ?? SwiftyJSONError.wrongType + return r + } else if rawArray.indices.contains(index) { + return JSON(rawArray[index]) + } else { + var r = JSON.null + r.error = SwiftyJSONError.indexOutOfBounds + return r + } + } + set { + if type == .array && + rawArray.indices.contains(index) && + newValue.error == nil { + rawArray[index] = newValue.object + } + } + } + + /// If `type` is `.dictionary`, return json whose object is `dictionary[key]` , otherwise return null json with error. + fileprivate subscript(key key: String) -> JSON { + get { + var r = JSON.null + if type == .dictionary { + if let o = rawDictionary[key] { + r = JSON(o) + } else { + r.error = SwiftyJSONError.notExist + } + } else { + r.error = self.error ?? SwiftyJSONError.wrongType + } + return r + } + set { + if type == .dictionary && newValue.error == nil { + rawDictionary[key] = newValue.object + } + } + } + + /// If `sub` is `Int`, return `subscript(index:)`; If `sub` is `String`, return `subscript(key:)`. + fileprivate subscript(sub sub: JSONSubscriptType) -> JSON { + get { + switch sub.jsonKey { + case .index(let index): return self[index: index] + case .key(let key): return self[key: key] + } + } + set { + switch sub.jsonKey { + case .index(let index): self[index: index] = newValue + case .key(let key): self[key: key] = newValue + } + } + } + + /** + Find a json in the complex data structures by using array of Int and/or String as path. + + Example: + + ```swift + let json = JSON[data] + let path = [9,"list","person","name"] + let name = json[path] + ``` + + The same as: let name = json[9]["list"]["person"]["name"] + + - parameter path: The target json's path. + + - returns: Return a json found by the path or a null json with error + */ + public subscript(path: [JSONSubscriptType]) -> JSON { + get { + return path.reduce(self) { $0[sub: $1] } + } + set { + switch path.count { + case 0: return + case 1: self[sub:path[0]].object = newValue.object + default: + var aPath = path + aPath.remove(at: 0) + var nextJSON = self[sub: path[0]] + nextJSON[aPath] = newValue + self[sub: path[0]] = nextJSON + } + } + } + + /** + Find a json in the complex data structures by using array of Int and/or String as path. + + - parameter path: The target json's path. Example: + ```swift + let name = json[9,"list","person","name"] + ``` + + The same as: + ```swift + let name = json[9]["list"]["person"]["name"] + ``` + + - returns: Return a json found by the path or a null json with error + */ + public subscript(path: JSONSubscriptType...) -> JSON { + get { + return self[path] + } + set { + self[path] = newValue + } + } +} + +// MARK: - LiteralConvertible + +extension JSON: Swift.ExpressibleByStringLiteral { + + public init(stringLiteral value: StringLiteralType) { + self.init(value) + } + + public init(extendedGraphemeClusterLiteral value: StringLiteralType) { + self.init(value) + } + + public init(unicodeScalarLiteral value: StringLiteralType) { + self.init(value) + } +} + +extension JSON: Swift.ExpressibleByIntegerLiteral { + + public init(integerLiteral value: IntegerLiteralType) { + self.init(value) + } +} + +extension JSON: Swift.ExpressibleByBooleanLiteral { + + public init(booleanLiteral value: BooleanLiteralType) { + self.init(value) + } +} + +extension JSON: Swift.ExpressibleByFloatLiteral { + + public init(floatLiteral value: FloatLiteralType) { + self.init(value) + } +} + +extension JSON: Swift.ExpressibleByDictionaryLiteral { + public init(dictionaryLiteral elements: (String, Any)...) { + let dictionary = Dictionary(elements, uniquingKeysWith: { $1 }) + self.init(dictionary) + } +} + +extension JSON: Swift.ExpressibleByArrayLiteral { + + public init(arrayLiteral elements: Any...) { + self.init(elements) + } +} + +// MARK: - Raw + +extension JSON: Swift.RawRepresentable { + + public init?(rawValue: Any) { + if JSON(rawValue).type == .unknown { + return nil + } else { + self.init(rawValue) + } + } + + public var rawValue: Any { + return object + } + + public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data { + guard JSONSerialization.isValidJSONObject(object) else { + throw SwiftyJSONError.invalidJSON + } + + return try JSONSerialization.data(withJSONObject: object, options: opt) + } + + public func rawString(_ encoding: String.Encoding = .utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? { + do { + return try _rawString(encoding, options: [.jsonSerialization: opt]) + } catch { + print("Could not serialize object to JSON because:", error.localizedDescription) + return nil + } + } + + public func rawString(_ options: [writingOptionsKeys: Any]) -> String? { + let encoding = options[.encoding] as? String.Encoding ?? String.Encoding.utf8 + let maxObjectDepth = options[.maxObjextDepth] as? Int ?? 10 + do { + return try _rawString(encoding, options: options, maxObjectDepth: maxObjectDepth) + } catch { + print("Could not serialize object to JSON because:", error.localizedDescription) + return nil + } + } + + fileprivate func _rawString(_ encoding: String.Encoding = .utf8, options: [writingOptionsKeys: Any], maxObjectDepth: Int = 10) throws -> String? { + guard maxObjectDepth > 0 else { throw SwiftyJSONError.invalidJSON } + switch type { + case .dictionary: + do { + if !(options[.castNilToNSNull] as? Bool ?? false) { + let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted + let data = try rawData(options: jsonOption) + return String(data: data, encoding: encoding) + } + + guard let dict = object as? [String: Any?] else { + return nil + } + let body = try dict.keys.map { key throws -> String in + guard let value = dict[key] else { + return "\"\(key)\": null" + } + guard let unwrappedValue = value else { + return "\"\(key)\": null" + } + + let nestedValue = JSON(unwrappedValue) + guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else { + throw SwiftyJSONError.elementTooDeep + } + if nestedValue.type == .string { + return "\"\(key)\": \"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\"" + } else { + return "\"\(key)\": \(nestedString)" + } + } + + return "{\(body.joined(separator: ","))}" + } catch _ { + return nil + } + case .array: + do { + if !(options[.castNilToNSNull] as? Bool ?? false) { + let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted + let data = try rawData(options: jsonOption) + return String(data: data, encoding: encoding) + } + + guard let array = object as? [Any?] else { + return nil + } + let body = try array.map { value throws -> String in + guard let unwrappedValue = value else { + return "null" + } + + let nestedValue = JSON(unwrappedValue) + guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else { + throw SwiftyJSONError.invalidJSON + } + if nestedValue.type == .string { + return "\"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\"" + } else { + return nestedString + } + } + + return "[\(body.joined(separator: ","))]" + } catch _ { + return nil + } + case .string: return rawString + case .number: return rawNumber.stringValue + case .bool: return rawBool.description + case .null: return "null" + default: return nil + } + } +} + +// MARK: - Printable, DebugPrintable + +extension JSON: Swift.CustomStringConvertible, Swift.CustomDebugStringConvertible { + + public var description: String { + return rawString(options: .prettyPrinted) ?? "unknown" + } + + public var debugDescription: String { + return description + } +} + +// MARK: - Array + +extension JSON { + + //Optional [JSON] + public var array: [JSON]? { + return type == .array ? rawArray.map(JSON.init(_:)) : nil + } + + //Non-optional [JSON] + public var arrayValue: [JSON] { + return self.array ?? [] + } + + //Optional [Any] + public var arrayObject: [Any]? { + get { + switch type { + case .array: return rawArray + default: return nil + } + } + set { + self.object = newValue ?? NSNull() + } + } +} + +// MARK: - Dictionary + +extension JSON { + + //Optional [String : JSON] + public var dictionary: [String: JSON]? { + if type == .dictionary { + return rawDictionary.mapValues(JSON.init(_:)) + } else { + return nil + } + } + + //Non-optional [String : JSON] + public var dictionaryValue: [String: JSON] { + return dictionary ?? [:] + } + + //Optional [String : Any] + + public var dictionaryObject: [String: Any]? { + get { + switch type { + case .dictionary: return rawDictionary + default: return nil + } + } + set { + object = newValue ?? NSNull() + } + } +} + +// MARK: - Bool + +extension JSON { // : Swift.Bool + + //Optional bool + public var bool: Bool? { + get { + switch type { + case .bool: return rawBool + default: return nil + } + } + set { + object = newValue ?? NSNull() + } + } + + //Non-optional bool + public var boolValue: Bool { + get { + switch type { + case .bool: return rawBool + case .number: return rawNumber.boolValue + case .string: return ["true", "y", "t", "yes", "1"].contains { rawString.caseInsensitiveCompare($0) == .orderedSame } + default: return false + } + } + set { + object = newValue + } + } +} + +// MARK: - String + +extension JSON { + + //Optional string + public var string: String? { + get { + switch type { + case .string: return object as? String + default: return nil + } + } + set { + object = newValue ?? NSNull() + } + } + + //Non-optional string + public var stringValue: String { + get { + switch type { + case .string: return object as? String ?? "" + case .number: return rawNumber.stringValue + case .bool: return (object as? Bool).map(String.init) ?? "" + default: return "" + } + } + set { + object = newValue + } + } +} + +// MARK: - Number + +extension JSON { + + //Optional number + public var number: NSNumber? { + get { + switch type { + case .number: return rawNumber + case .bool: return NSNumber(value: rawBool ? 1 : 0) + default: return nil + } + } + set { + object = newValue ?? NSNull() + } + } + + //Non-optional number + public var numberValue: NSNumber { + get { + switch type { + case .string: + let decimal = NSDecimalNumber(string: object as? String) + return decimal == .notANumber ? .zero : decimal + case .number: return object as? NSNumber ?? NSNumber(value: 0) + case .bool: return NSNumber(value: rawBool ? 1 : 0) + default: return NSNumber(value: 0.0) + } + } + set { + object = newValue + } + } +} + +// MARK: - Null + +extension JSON { + + public var null: NSNull? { + set { + object = NSNull() + } + get { + switch type { + case .null: return rawNull + default: return nil + } + } + } + public func exists() -> Bool { + if let errorValue = error, (400...1000).contains(errorValue.errorCode) { + return false + } + return true + } +} + +// MARK: - URL + +extension JSON { + + //Optional URL + public var url: URL? { + get { + switch type { + case .string: + // Check for existing percent escapes first to prevent double-escaping of % character + if rawString.range(of: "%[0-9A-Fa-f]{2}", options: .regularExpression, range: nil, locale: nil) != nil { + return Foundation.URL(string: rawString) + } else if let encodedString_ = rawString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) { + // We have to use `Foundation.URL` otherwise it conflicts with the variable name. + return Foundation.URL(string: encodedString_) + } else { + return nil + } + default: + return nil + } + } + set { + object = newValue?.absoluteString ?? NSNull() + } + } +} + +// MARK: - Int, Double, Float, Int8, Int16, Int32, Int64 + +extension JSON { + + public var double: Double? { + get { + return number?.doubleValue + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var doubleValue: Double { + get { + return numberValue.doubleValue + } + set { + object = NSNumber(value: newValue) + } + } + + public var float: Float? { + get { + return number?.floatValue + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var floatValue: Float { + get { + return numberValue.floatValue + } + set { + object = NSNumber(value: newValue) + } + } + + public var int: Int? { + get { + return number?.intValue + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var intValue: Int { + get { + return numberValue.intValue + } + set { + object = NSNumber(value: newValue) + } + } + + public var uInt: UInt? { + get { + return number?.uintValue + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var uIntValue: UInt { + get { + return numberValue.uintValue + } + set { + object = NSNumber(value: newValue) + } + } + + public var int8: Int8? { + get { + return number?.int8Value + } + set { + if let newValue = newValue { + object = NSNumber(value: Int(newValue)) + } else { + object = NSNull() + } + } + } + + public var int8Value: Int8 { + get { + return numberValue.int8Value + } + set { + object = NSNumber(value: Int(newValue)) + } + } + + public var uInt8: UInt8? { + get { + return number?.uint8Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var uInt8Value: UInt8 { + get { + return numberValue.uint8Value + } + set { + object = NSNumber(value: newValue) + } + } + + public var int16: Int16? { + get { + return number?.int16Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var int16Value: Int16 { + get { + return numberValue.int16Value + } + set { + object = NSNumber(value: newValue) + } + } + + public var uInt16: UInt16? { + get { + return number?.uint16Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var uInt16Value: UInt16 { + get { + return numberValue.uint16Value + } + set { + object = NSNumber(value: newValue) + } + } + + public var int32: Int32? { + get { + return number?.int32Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var int32Value: Int32 { + get { + return numberValue.int32Value + } + set { + object = NSNumber(value: newValue) + } + } + + public var uInt32: UInt32? { + get { + return number?.uint32Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var uInt32Value: UInt32 { + get { + return numberValue.uint32Value + } + set { + object = NSNumber(value: newValue) + } + } + + public var int64: Int64? { + get { + return number?.int64Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var int64Value: Int64 { + get { + return numberValue.int64Value + } + set { + object = NSNumber(value: newValue) + } + } + + public var uInt64: UInt64? { + get { + return number?.uint64Value + } + set { + if let newValue = newValue { + object = NSNumber(value: newValue) + } else { + object = NSNull() + } + } + } + + public var uInt64Value: UInt64 { + get { + return numberValue.uint64Value + } + set { + object = NSNumber(value: newValue) + } + } +} + +// MARK: - Comparable + +extension JSON: Swift.Comparable {} + +public func == (lhs: JSON, rhs: JSON) -> Bool { + + switch (lhs.type, rhs.type) { + case (.number, .number): return lhs.rawNumber == rhs.rawNumber + case (.string, .string): return lhs.rawString == rhs.rawString + case (.bool, .bool): return lhs.rawBool == rhs.rawBool + case (.array, .array): return lhs.rawArray as NSArray == rhs.rawArray as NSArray + case (.dictionary, .dictionary): return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary + case (.null, .null): return true + default: return false + } +} + +public func <= (lhs: JSON, rhs: JSON) -> Bool { + + switch (lhs.type, rhs.type) { + case (.number, .number): return lhs.rawNumber <= rhs.rawNumber + case (.string, .string): return lhs.rawString <= rhs.rawString + case (.bool, .bool): return lhs.rawBool == rhs.rawBool + case (.array, .array): return lhs.rawArray as NSArray == rhs.rawArray as NSArray + case (.dictionary, .dictionary): return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary + case (.null, .null): return true + default: return false + } +} + +public func >= (lhs: JSON, rhs: JSON) -> Bool { + + switch (lhs.type, rhs.type) { + case (.number, .number): return lhs.rawNumber >= rhs.rawNumber + case (.string, .string): return lhs.rawString >= rhs.rawString + case (.bool, .bool): return lhs.rawBool == rhs.rawBool + case (.array, .array): return lhs.rawArray as NSArray == rhs.rawArray as NSArray + case (.dictionary, .dictionary): return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary + case (.null, .null): return true + default: return false + } +} + +public func > (lhs: JSON, rhs: JSON) -> Bool { + + switch (lhs.type, rhs.type) { + case (.number, .number): return lhs.rawNumber > rhs.rawNumber + case (.string, .string): return lhs.rawString > rhs.rawString + default: return false + } +} + +public func < (lhs: JSON, rhs: JSON) -> Bool { + + switch (lhs.type, rhs.type) { + case (.number, .number): return lhs.rawNumber < rhs.rawNumber + case (.string, .string): return lhs.rawString < rhs.rawString + default: return false + } +} + +private let trueNumber = NSNumber(value: true) +private let falseNumber = NSNumber(value: false) +private let trueObjCType = String(cString: trueNumber.objCType) +private let falseObjCType = String(cString: falseNumber.objCType) + +// MARK: - NSNumber: Comparable + +extension NSNumber { + fileprivate var isBool: Bool { + let objCType = String(cString: self.objCType) + if (self.compare(trueNumber) == .orderedSame && objCType == trueObjCType) || (self.compare(falseNumber) == .orderedSame && objCType == falseObjCType) { + return true + } else { + return false + } + } +} + +func == (lhs: NSNumber, rhs: NSNumber) -> Bool { + switch (lhs.isBool, rhs.isBool) { + case (false, true): return false + case (true, false): return false + default: return lhs.compare(rhs) == .orderedSame + } +} + +func != (lhs: NSNumber, rhs: NSNumber) -> Bool { + return !(lhs == rhs) +} + +func < (lhs: NSNumber, rhs: NSNumber) -> Bool { + + switch (lhs.isBool, rhs.isBool) { + case (false, true): return false + case (true, false): return false + default: return lhs.compare(rhs) == .orderedAscending + } +} + +func > (lhs: NSNumber, rhs: NSNumber) -> Bool { + + switch (lhs.isBool, rhs.isBool) { + case (false, true): return false + case (true, false): return false + default: return lhs.compare(rhs) == ComparisonResult.orderedDescending + } +} + +func <= (lhs: NSNumber, rhs: NSNumber) -> Bool { + + switch (lhs.isBool, rhs.isBool) { + case (false, true): return false + case (true, false): return false + default: return lhs.compare(rhs) != .orderedDescending + } +} + +func >= (lhs: NSNumber, rhs: NSNumber) -> Bool { + + switch (lhs.isBool, rhs.isBool) { + case (false, true): return false + case (true, false): return false + default: return lhs.compare(rhs) != .orderedAscending + } +} + +public enum writingOptionsKeys { + case jsonSerialization + case castNilToNSNull + case maxObjextDepth + case encoding +} + +// MARK: - JSON: Codable +extension JSON: Codable { + private static var codableTypes: [Codable.Type] { + return [ + Bool.self, + Int.self, + Int8.self, + Int16.self, + Int32.self, + Int64.self, + UInt.self, + UInt8.self, + UInt16.self, + UInt32.self, + UInt64.self, + Double.self, + String.self, + [JSON].self, + [String: JSON].self + ] + } + public init(from decoder: Decoder) throws { + var object: Any? + + if let container = try? decoder.singleValueContainer(), !container.decodeNil() { + for type in JSON.codableTypes { + if object != nil { + break + } + // try to decode value + switch type { + case let boolType as Bool.Type: + object = try? container.decode(boolType) + case let intType as Int.Type: + object = try? container.decode(intType) + case let int8Type as Int8.Type: + object = try? container.decode(int8Type) + case let int32Type as Int32.Type: + object = try? container.decode(int32Type) + case let int64Type as Int64.Type: + object = try? container.decode(int64Type) + case let uintType as UInt.Type: + object = try? container.decode(uintType) + case let uint8Type as UInt8.Type: + object = try? container.decode(uint8Type) + case let uint16Type as UInt16.Type: + object = try? container.decode(uint16Type) + case let uint32Type as UInt32.Type: + object = try? container.decode(uint32Type) + case let uint64Type as UInt64.Type: + object = try? container.decode(uint64Type) + case let doubleType as Double.Type: + object = try? container.decode(doubleType) + case let stringType as String.Type: + object = try? container.decode(stringType) + case let jsonValueArrayType as [JSON].Type: + object = try? container.decode(jsonValueArrayType) + case let jsonValueDictType as [String: JSON].Type: + object = try? container.decode(jsonValueDictType) + default: + break + } + } + } + self.init(object ?? NSNull()) + } + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + if object is NSNull { + try container.encodeNil() + return + } + switch object { + case let intValue as Int: + try container.encode(intValue) + case let int8Value as Int8: + try container.encode(int8Value) + case let int32Value as Int32: + try container.encode(int32Value) + case let int64Value as Int64: + try container.encode(int64Value) + case let uintValue as UInt: + try container.encode(uintValue) + case let uint8Value as UInt8: + try container.encode(uint8Value) + case let uint16Value as UInt16: + try container.encode(uint16Value) + case let uint32Value as UInt32: + try container.encode(uint32Value) + case let uint64Value as UInt64: + try container.encode(uint64Value) + case let doubleValue as Double: + try container.encode(doubleValue) + case let boolValue as Bool: + try container.encode(boolValue) + case let stringValue as String: + try container.encode(stringValue) + case is [Any]: + let jsonValueArray = array ?? [] + try container.encode(jsonValueArray) + case is [String: Any]: + let jsonValueDictValue = dictionary ?? [:] + try container.encode(jsonValueDictValue) + default: + break + } + } +} diff --git a/SwiftyJSON.podspec b/SwiftyJSON.podspec index 2d822e31..dd091231 100644 --- a/SwiftyJSON.podspec +++ b/SwiftyJSON.podspec @@ -1,19 +1,18 @@ Pod::Spec.new do |s| s.name = "SwiftyJSON" - s.version = "3.1.4" + s.version = "5.0.2" s.summary = "SwiftyJSON makes it easy to deal with JSON data in Swift" s.homepage = "https://github.com/SwiftyJSON/SwiftyJSON" s.license = { :type => "MIT" } s.authors = { "lingoer" => "lingoerer@gmail.com", "tangplin" => "tangplin@gmail.com" } s.requires_arc = true + s.swift_version = "5.0" s.osx.deployment_target = "10.9" - s.ios.deployment_target = "8.0" - s.watchos.deployment_target = "2.0" + s.ios.deployment_target = "9.0" + s.watchos.deployment_target = "3.0" s.tvos.deployment_target = "9.0" s.source = { :git => "https://github.com/SwiftyJSON/SwiftyJSON.git", :tag => s.version } - s.source_files = "Source/*.swift" - s.pod_target_xcconfig = { - 'SWIFT_VERSION' => '3.0', - } + s.source_files = "Source/SwiftyJSON/*.swift" + s.resource_bundles = {'SwiftyJSON' => ['Source/SwiftyJSON/PrivacyInfo.xcprivacy']} end diff --git a/SwiftyJSON.xcodeproj/project.pbxproj b/SwiftyJSON.xcodeproj/project.pbxproj index 985b9fc5..3c325ac2 100644 --- a/SwiftyJSON.xcodeproj/project.pbxproj +++ b/SwiftyJSON.xcodeproj/project.pbxproj @@ -6,6 +6,20 @@ objectVersion = 46; objects = { +/* Begin PBXAggregateTarget section */ + A81D162B1E5743B000C62C5F /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A81D162E1E5743B000C62C5F /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + A81D162F1E5743CE00C62C5F /* ShellScript */, + ); + dependencies = ( + ); + name = SwiftLint; + productName = SwiftLint; + }; +/* End PBXAggregateTarget section */ + /* Begin PBXBuildFile section */ 1B587CC61DDE04770012D8DB /* MergeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B587CC41DDE04360012D8DB /* MergeTests.swift */; }; 1B587CC71DDE04780012D8DB /* MergeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B587CC41DDE04360012D8DB /* MergeTests.swift */; }; @@ -15,6 +29,9 @@ 5DD502911D9B21810004C112 /* NestedJSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DD502901D9B21810004C112 /* NestedJSONTests.swift */; }; 5DD502921D9B21810004C112 /* NestedJSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DD502901D9B21810004C112 /* NestedJSONTests.swift */; }; 5DD502931D9B21810004C112 /* NestedJSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DD502901D9B21810004C112 /* NestedJSONTests.swift */; }; + 712921EF2004E4EB00DA6340 /* CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712921EE2004E4EB00DA6340 /* CodableTests.swift */; }; + 712921F02004E4EB00DA6340 /* CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712921EE2004E4EB00DA6340 /* CodableTests.swift */; }; + 712921F12004E4EB00DA6340 /* CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712921EE2004E4EB00DA6340 /* CodableTests.swift */; }; 7236B4EE1BAC14150020529B /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */; }; 7236B4F11BAC14150020529B /* SwiftyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4FEFE019575BE100351305 /* SwiftyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C459EF41A910334008C9A41 /* SwiftyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4FEFE019575BE100351305 /* SwiftyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -34,11 +51,18 @@ 9C459F041A9103C1008C9A41 /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8B19E51D6500540692 /* DictionaryTests.swift */; }; 9C459F051A9103C1008C9A41 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8D19E52F4200540692 /* ArrayTests.swift */; }; 9C7DFC661A9102BD005AA3F7 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */; }; + A1DE64C62BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; }; + A1DE64C72BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; }; + A1DE64C82BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; }; + A1DE64C92BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */; }; A819C49719E1A7DD00ADCC3D /* LiteralConvertibleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */; }; A819C49919E1B10300ADCC3D /* RawRepresentableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */; }; A819C49F19E2EE5B00ADCC3D /* SubscriptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */; }; A819C4A119E37FC600ADCC3D /* PrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C4A019E37FC600ADCC3D /* PrintableTests.swift */; }; A81CBA0B1BCF6B0200A649A2 /* Tests.json in Resources */ = {isa = PBXBuildFile; fileRef = A885D1DA19CFCFF0002FD4C3 /* Tests.json */; }; + A830A6951E5B2DD8001D7F6D /* MutabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A830A6941E5B2DD8001D7F6D /* MutabilityTests.swift */; }; + A830A6961E5B2DD8001D7F6D /* MutabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A830A6941E5B2DD8001D7F6D /* MutabilityTests.swift */; }; + A830A6971E5B2DD8001D7F6D /* MutabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A830A6941E5B2DD8001D7F6D /* MutabilityTests.swift */; }; A8491E1E19CD6DAE00CCFAE6 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */; }; A8580F791BCF5C5B00DA927B /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7236B4F61BAC14150020529B /* SwiftyJSON.framework */; }; A8580F801BCF69A000DA927B /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */; }; @@ -93,36 +117,39 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 030B6CDC1A6E171D00C2D4F1 /* Info-OSX.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-OSX.plist"; sourceTree = ""; }; - 1B587CC41DDE04360012D8DB /* MergeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergeTests.swift; sourceTree = ""; }; + 030B6CDC1A6E171D00C2D4F1 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = ""; }; + 1B587CC41DDE04360012D8DB /* MergeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MergeTests.swift; path = ../SwiftJSONTests/MergeTests.swift; sourceTree = ""; }; 2E4FEFDB19575BE100351305 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2E4FEFDF19575BE100351305 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; - 2E4FEFE019575BE100351305 /* SwiftyJSON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftyJSON.h; sourceTree = ""; }; + 2E4FEFE019575BE100351305 /* SwiftyJSON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SwiftyJSON.h; path = SwiftyJSON/SwiftyJSON.h; sourceTree = ""; }; 2E4FEFE619575BE100351305 /* SwiftyJSON iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftyJSON iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 5DD502901D9B21810004C112 /* NestedJSONTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NestedJSONTests.swift; sourceTree = ""; }; + 5DD502901D9B21810004C112 /* NestedJSONTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NestedJSONTests.swift; path = ../SwiftJSONTests/NestedJSONTests.swift; sourceTree = ""; }; + 712921EE2004E4EB00DA6340 /* CodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CodableTests.swift; path = ../SwiftJSONTests/CodableTests.swift; sourceTree = ""; }; 7236B4F61BAC14150020529B /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7236B4F71BAC14150020529B /* Info-tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-tvOS.plist"; sourceTree = ""; }; - 9C459EF61A9103B1008C9A41 /* Info-OSX.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-OSX.plist"; sourceTree = ""; }; + 9C459EF61A9103B1008C9A41 /* Info-macOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Info-macOS.plist"; path = "../Info-macOS.plist"; sourceTree = ""; }; 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON OSX Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftyJSON OSX Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiteralConvertibleTests.swift; sourceTree = ""; }; - A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawRepresentableTests.swift; sourceTree = ""; }; - A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscriptTests.swift; sourceTree = ""; }; - A819C4A019E37FC600ADCC3D /* PrintableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrintableTests.swift; sourceTree = ""; }; - A82A1C0D19D922DC009A653D /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; - A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyJSON.swift; sourceTree = ""; }; + 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftyJSON macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = SwiftyJSON/PrivacyInfo.xcprivacy; sourceTree = ""; }; + A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LiteralConvertibleTests.swift; path = ../SwiftJSONTests/LiteralConvertibleTests.swift; sourceTree = ""; }; + A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RawRepresentableTests.swift; path = ../SwiftJSONTests/RawRepresentableTests.swift; sourceTree = ""; }; + A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SubscriptTests.swift; path = ../SwiftJSONTests/SubscriptTests.swift; sourceTree = ""; }; + A819C4A019E37FC600ADCC3D /* PrintableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PrintableTests.swift; path = ../SwiftJSONTests/PrintableTests.swift; sourceTree = ""; }; + A82A1C0D19D922DC009A653D /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Info-iOS.plist"; path = "../Info-iOS.plist"; sourceTree = ""; }; + A830A6941E5B2DD8001D7F6D /* MutabilityTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MutabilityTests.swift; path = ../SwiftJSONTests/MutabilityTests.swift; sourceTree = ""; }; + A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyJSON.swift; path = SwiftyJSON/SwiftyJSON.swift; sourceTree = ""; }; A8580F741BCF5C5B00DA927B /* SwiftyJSON tvOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftyJSON tvOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - A8580F781BCF5C5B00DA927B /* Info-tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-tvOS.plist"; sourceTree = ""; }; - A863BE2719EED46F0092A41F /* RawTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawTests.swift; sourceTree = ""; }; - A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerformanceTests.swift; sourceTree = ""; }; - A87080E319E3C2A600CDE086 /* SequenceTypeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceTypeTests.swift; sourceTree = ""; }; - A87080E519E3DF7800CDE086 /* ComparableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComparableTests.swift; sourceTree = ""; }; - A87080E719E439DA00CDE086 /* NumberTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberTests.swift; sourceTree = ""; }; - A87080E919E43C0700CDE086 /* StringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = ""; }; - A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTests.swift; sourceTree = ""; }; + A8580F781BCF5C5B00DA927B /* Info-tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-tvOS.plist"; path = "../Info-tvOS.plist"; sourceTree = ""; }; + A863BE2719EED46F0092A41F /* RawTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RawTests.swift; path = ../SwiftJSONTests/RawTests.swift; sourceTree = ""; }; + A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PerformanceTests.swift; path = ../SwiftJSONTests/PerformanceTests.swift; sourceTree = ""; }; + A87080E319E3C2A600CDE086 /* SequenceTypeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SequenceTypeTests.swift; path = ../SwiftJSONTests/SequenceTypeTests.swift; sourceTree = ""; }; + A87080E519E3DF7800CDE086 /* ComparableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ComparableTests.swift; path = ../SwiftJSONTests/ComparableTests.swift; sourceTree = ""; }; + A87080E719E439DA00CDE086 /* NumberTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NumberTests.swift; path = ../SwiftJSONTests/NumberTests.swift; sourceTree = ""; }; + A87080E919E43C0700CDE086 /* StringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StringTests.swift; path = ../SwiftJSONTests/StringTests.swift; sourceTree = ""; }; + A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BaseTests.swift; path = ../SwiftJSONTests/BaseTests.swift; sourceTree = ""; }; A885D1DA19CFCFF0002FD4C3 /* Tests.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Tests.json; sourceTree = ""; }; - A8B66C8B19E51D6500540692 /* DictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryTests.swift; sourceTree = ""; }; - A8B66C8D19E52F4200540692 /* ArrayTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayTests.swift; sourceTree = ""; }; + A8B66C8B19E51D6500540692 /* DictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DictionaryTests.swift; path = ../SwiftJSONTests/DictionaryTests.swift; sourceTree = ""; }; + A8B66C8D19E52F4200540692 /* ArrayTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ArrayTests.swift; path = ../SwiftJSONTests/ArrayTests.swift; sourceTree = ""; }; E4D7CCE81B9465A700EE7221 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E4D7CCE91B9465A800EE7221 /* Info-watchOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-watchOS.plist"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -187,7 +214,7 @@ isa = PBXGroup; children = ( 2E4FEFDD19575BE100351305 /* Source */, - 2E4FEFEA19575BE100351305 /* SwiftyJSONTests */, + 2E4FEFEA19575BE100351305 /* Tests */, 2E4FEFDC19575BE100351305 /* Products */, ); sourceTree = ""; @@ -198,7 +225,7 @@ 2E4FEFDB19575BE100351305 /* SwiftyJSON.framework */, 2E4FEFE619575BE100351305 /* SwiftyJSON iOS Tests.xctest */, 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */, - 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON OSX Tests.xctest */, + 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON macOS Tests.xctest */, E4D7CCE81B9465A700EE7221 /* SwiftyJSON.framework */, 7236B4F61BAC14150020529B /* SwiftyJSON.framework */, A8580F741BCF5C5B00DA927B /* SwiftyJSON tvOS Tests.xctest */, @@ -219,19 +246,19 @@ 2E4FEFDE19575BE100351305 /* Supporting Files */ = { isa = PBXGroup; children = ( + A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */, 2E4FEFDF19575BE100351305 /* Info-iOS.plist */, - 030B6CDC1A6E171D00C2D4F1 /* Info-OSX.plist */, + 030B6CDC1A6E171D00C2D4F1 /* Info-macOS.plist */, E4D7CCE91B9465A800EE7221 /* Info-watchOS.plist */, 7236B4F71BAC14150020529B /* Info-tvOS.plist */, ); name = "Supporting Files"; sourceTree = ""; }; - 2E4FEFEA19575BE100351305 /* SwiftyJSONTests */ = { + 2E4FEFEA19575BE100351305 /* Tests */ = { isa = PBXGroup; children = ( 1B587CC41DDE04360012D8DB /* MergeTests.swift */, - A885D1DA19CFCFF0002FD4C3 /* Tests.json */, A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */, A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */, 5DD502901D9B21810004C112 /* NestedJSONTests.swift */, @@ -245,18 +272,21 @@ A87080E719E439DA00CDE086 /* NumberTests.swift */, A863BE2719EED46F0092A41F /* RawTests.swift */, A8B66C8B19E51D6500540692 /* DictionaryTests.swift */, + A830A6941E5B2DD8001D7F6D /* MutabilityTests.swift */, A8B66C8D19E52F4200540692 /* ArrayTests.swift */, + 712921EE2004E4EB00DA6340 /* CodableTests.swift */, 2E4FEFEB19575BE100351305 /* Supporting Files */, ); - name = SwiftyJSONTests; - path = Tests/SwiftyJSONTests; + name = Tests; + path = Tests/SwiftJSONTests; sourceTree = ""; }; 2E4FEFEB19575BE100351305 /* Supporting Files */ = { isa = PBXGroup; children = ( + A885D1DA19CFCFF0002FD4C3 /* Tests.json */, A82A1C0D19D922DC009A653D /* Info-iOS.plist */, - 9C459EF61A9103B1008C9A41 /* Info-OSX.plist */, + 9C459EF61A9103B1008C9A41 /* Info-macOS.plist */, A8580F781BCF5C5B00DA927B /* Info-tvOS.plist */, ); name = "Supporting Files"; @@ -304,9 +334,9 @@ isa = PBXNativeTarget; buildConfigurationList = 2E4FEFF119575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON iOS" */; buildPhases = ( + 2E4FEFD819575BE100351305 /* Headers */, 2E4FEFD619575BE100351305 /* Sources */, 2E4FEFD719575BE100351305 /* Frameworks */, - 2E4FEFD819575BE100351305 /* Headers */, 2E4FEFD919575BE100351305 /* Resources */, ); buildRules = ( @@ -340,9 +370,9 @@ isa = PBXNativeTarget; buildConfigurationList = 7236B4F31BAC14150020529B /* Build configuration list for PBXNativeTarget "SwiftyJSON tvOS" */; buildPhases = ( + 7236B4F01BAC14150020529B /* Headers */, 7236B4ED1BAC14150020529B /* Sources */, 7236B4EF1BAC14150020529B /* Frameworks */, - 7236B4F01BAC14150020529B /* Headers */, 7236B4F21BAC14150020529B /* Resources */, ); buildRules = ( @@ -354,27 +384,27 @@ productReference = 7236B4F61BAC14150020529B /* SwiftyJSON.framework */; productType = "com.apple.product-type.framework"; }; - 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON OSX */ = { + 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON macOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 9C7DFC6E1A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON OSX" */; + buildConfigurationList = 9C7DFC6E1A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS" */; buildPhases = ( + 9C7DFC581A9102BD005AA3F7 /* Headers */, 9C7DFC561A9102BD005AA3F7 /* Sources */, 9C7DFC571A9102BD005AA3F7 /* Frameworks */, - 9C7DFC581A9102BD005AA3F7 /* Headers */, 9C7DFC591A9102BD005AA3F7 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = "SwiftyJSON OSX"; + name = "SwiftyJSON macOS"; productName = "SwiftyJSON OSX"; productReference = 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */; productType = "com.apple.product-type.framework"; }; - 9C7DFC641A9102BD005AA3F7 /* SwiftyJSON OSX Tests */ = { + 9C7DFC641A9102BD005AA3F7 /* SwiftyJSON macOS Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 9C7DFC711A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON OSX Tests" */; + buildConfigurationList = 9C7DFC711A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS Tests" */; buildPhases = ( 9C7DFC611A9102BD005AA3F7 /* Sources */, 9C7DFC621A9102BD005AA3F7 /* Frameworks */, @@ -385,9 +415,9 @@ dependencies = ( 9C7DFC681A9102BD005AA3F7 /* PBXTargetDependency */, ); - name = "SwiftyJSON OSX Tests"; + name = "SwiftyJSON macOS Tests"; productName = "SwiftyJSON OSXTests"; - productReference = 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON OSX Tests.xctest */; + productReference = 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON macOS Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; A8580F731BCF5C5B00DA927B /* SwiftyJSON tvOS Tests */ = { @@ -412,9 +442,9 @@ isa = PBXNativeTarget; buildConfigurationList = E4D7CCE51B9465A700EE7221 /* Build configuration list for PBXNativeTarget "SwiftyJSON watchOS" */; buildPhases = ( + E4D7CCE21B9465A700EE7221 /* Headers */, E4D7CCDF1B9465A700EE7221 /* Sources */, E4D7CCE11B9465A700EE7221 /* Frameworks */, - E4D7CCE21B9465A700EE7221 /* Headers */, E4D7CCE41B9465A700EE7221 /* Resources */, ); buildRules = ( @@ -433,43 +463,53 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0820; + LastUpgradeCheck = 1020; TargetAttributes = { 2E4FEFDA19575BE100351305 = { CreatedOnToolsVersion = 6.0; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; ProvisioningStyle = Automatic; }; 2E4FEFE519575BE100351305 = { CreatedOnToolsVersion = 6.0; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; ProvisioningStyle = Manual; TestTargetID = 2E4FEFDA19575BE100351305; }; 7236B4EC1BAC14150020529B = { + LastSwiftMigration = 1000; ProvisioningStyle = Automatic; }; 9C7DFC5A1A9102BD005AA3F7 = { CreatedOnToolsVersion = 6.1.1; + LastSwiftMigration = 1000; ProvisioningStyle = Automatic; }; 9C7DFC641A9102BD005AA3F7 = { CreatedOnToolsVersion = 6.1.1; + LastSwiftMigration = 1000; + }; + A81D162B1E5743B000C62C5F = { + CreatedOnToolsVersion = 8.2.1; + ProvisioningStyle = Automatic; }; A8580F731BCF5C5B00DA927B = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 1000; }; E4D7CCDE1B9465A700EE7221 = { + LastSwiftMigration = 1000; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 2E4FEFD519575BE100351305 /* Build configuration list for PBXProject "SwiftyJSON" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 2E4FEFD119575BE100351305; productRefGroup = 2E4FEFDC19575BE100351305 /* Products */; @@ -478,11 +518,12 @@ targets = ( 2E4FEFDA19575BE100351305 /* SwiftyJSON iOS */, 2E4FEFE519575BE100351305 /* SwiftyJSON iOS Tests */, - 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON OSX */, - 9C7DFC641A9102BD005AA3F7 /* SwiftyJSON OSX Tests */, + 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON macOS */, + 9C7DFC641A9102BD005AA3F7 /* SwiftyJSON macOS Tests */, E4D7CCDE1B9465A700EE7221 /* SwiftyJSON watchOS */, 7236B4EC1BAC14150020529B /* SwiftyJSON tvOS */, A8580F731BCF5C5B00DA927B /* SwiftyJSON tvOS Tests */, + A81D162B1E5743B000C62C5F /* SwiftLint */, ); }; /* End PBXProject section */ @@ -492,6 +533,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A1DE64C62BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -507,6 +549,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A1DE64C92BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -514,6 +557,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A1DE64C72BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -537,11 +581,28 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A1DE64C82BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + A81D162F1E5743CE00C62C5F /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 2E4FEFD619575BE100351305 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -562,7 +623,9 @@ A86BAA0E19EBC32B009EAAEB /* PerformanceTests.swift in Sources */, A819C49919E1B10300ADCC3D /* RawRepresentableTests.swift in Sources */, A819C49F19E2EE5B00ADCC3D /* SubscriptTests.swift in Sources */, + A830A6951E5B2DD8001D7F6D /* MutabilityTests.swift in Sources */, A863BE2819EED46F0092A41F /* RawTests.swift in Sources */, + 712921EF2004E4EB00DA6340 /* CodableTests.swift in Sources */, A885D1D219CF1EE6002FD4C3 /* BaseTests.swift in Sources */, A8B66C8E19E52F4200540692 /* ArrayTests.swift in Sources */, A8B66C8C19E51D6500540692 /* DictionaryTests.swift in Sources */, @@ -600,7 +663,9 @@ 9C459F021A9103C1008C9A41 /* NumberTests.swift in Sources */, 9C459EFF1A9103C1008C9A41 /* RawRepresentableTests.swift in Sources */, 9C459EFA1A9103C1008C9A41 /* BaseTests.swift in Sources */, + A830A6961E5B2DD8001D7F6D /* MutabilityTests.swift in Sources */, 9C459F041A9103C1008C9A41 /* DictionaryTests.swift in Sources */, + 712921F02004E4EB00DA6340 /* CodableTests.swift in Sources */, 9C459EF91A9103C1008C9A41 /* PerformanceTests.swift in Sources */, 9C459EFE1A9103C1008C9A41 /* LiteralConvertibleTests.swift in Sources */, 9C459EFC1A9103C1008C9A41 /* PrintableTests.swift in Sources */, @@ -622,7 +687,9 @@ A8580F821BCF69A000DA927B /* SequenceTypeTests.swift in Sources */, A8580F831BCF69A000DA927B /* PrintableTests.swift in Sources */, A8580F841BCF69A000DA927B /* SubscriptTests.swift in Sources */, + A830A6971E5B2DD8001D7F6D /* MutabilityTests.swift in Sources */, A8580F851BCF69A000DA927B /* LiteralConvertibleTests.swift in Sources */, + 712921F12004E4EB00DA6340 /* CodableTests.swift in Sources */, A8580F861BCF69A000DA927B /* RawRepresentableTests.swift in Sources */, A8580F871BCF69A000DA927B /* ComparableTests.swift in Sources */, A8580F881BCF69A000DA927B /* StringTests.swift in Sources */, @@ -651,7 +718,7 @@ }; 9C7DFC681A9102BD005AA3F7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON OSX */; + target = 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON macOS */; targetProxy = 9C7DFC671A9102BD005AA3F7 /* PBXContainerItemProxy */; }; A8580F7B1BCF5C5B00DA927B /* PBXTargetDependency */ = { @@ -666,18 +733,27 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -701,7 +777,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; METAL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -718,18 +794,27 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -747,7 +832,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; METAL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; @@ -771,14 +856,17 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = 0; INFOPLIST_FILE = "Source/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = SwiftyJSON; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -793,14 +881,16 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = s; INFOPLIST_FILE = "Source/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = SwiftyJSON; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -809,17 +899,20 @@ buildSettings = { CODE_SIGN_IDENTITY = ""; DEVELOPMENT_TEAM = ""; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = "Tests/SwiftyJSONTests/Info-iOS.plist"; + INFOPLIST_FILE = "Tests/Info-iOS.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; METAL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -828,13 +921,15 @@ buildSettings = { CODE_SIGN_IDENTITY = ""; DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "Tests/SwiftyJSONTests/Info-iOS.plist"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = "Tests/Info-iOS.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; METAL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -849,14 +944,16 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = 0; INFOPLIST_FILE = "Source/Info-tvOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = SwiftyJSON; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -873,14 +970,15 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = s; INFOPLIST_FILE = "Source/Info-tvOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = SwiftyJSON; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -897,11 +995,12 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = "Source/Info-OSX.plist"; + INFOPLIST_FILE = "Source/Info-macOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; @@ -911,6 +1010,8 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -926,7 +1027,8 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - INFOPLIST_FILE = "Source/Info-OSX.plist"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = "Source/Info-macOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; @@ -936,6 +1038,7 @@ PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -945,17 +1048,20 @@ CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ""; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = "Tests/SwiftyJSONTests/Info-OSX.plist"; + INFOPLIST_FILE = "Tests/Info-macOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -966,13 +1072,31 @@ COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ""; - INFOPLIST_FILE = "Tests/SwiftyJSONTests/Info-OSX.plist"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = "Tests/Info-macOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + A81D162C1E5743B000C62C5F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + A81D162D1E5743B000C62C5F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; }; name = Release; }; @@ -982,12 +1106,15 @@ CODE_SIGN_IDENTITY = ""; DEBUG_INFORMATION_FORMAT = dwarf; GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Tests/SwiftyJSONTests/Info-tvOS.plist"; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = "Tests/Info-tvOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.tangplin.SwiftyJSON-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; }; name = Debug; @@ -999,12 +1126,14 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Tests/SwiftyJSONTests/Info-tvOS.plist"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = "Tests/Info-tvOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "com.tangplin.SwiftyJSON-tvOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; }; name = Release; @@ -1021,7 +1150,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Source/Info-OSX.plist"; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = "Source/Info-macOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; @@ -1029,8 +1159,10 @@ SDKROOT = watchos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "watchsimulator watchos"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 2.0; + WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Debug; }; @@ -1046,7 +1178,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Source/Info-OSX.plist"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = "Source/Info-macOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; @@ -1054,8 +1187,9 @@ SDKROOT = watchos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "watchsimulator watchos"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; - WATCHOS_DEPLOYMENT_TARGET = 2.0; + WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Release; }; @@ -1098,7 +1232,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9C7DFC6E1A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON OSX" */ = { + 9C7DFC6E1A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 9C7DFC6F1A9102BD005AA3F7 /* Debug */, @@ -1107,7 +1241,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9C7DFC711A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON OSX Tests" */ = { + 9C7DFC711A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 9C7DFC721A9102BD005AA3F7 /* Debug */, @@ -1116,6 +1250,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + A81D162E1E5743B000C62C5F /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A81D162C1E5743B000C62C5F /* Debug */, + A81D162D1E5743B000C62C5F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; A8580F7C1BCF5C5B00DA927B /* Build configuration list for PBXNativeTarget "SwiftyJSON tvOS Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/SwiftyJSON.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftyJSON.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SwiftyJSON.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON iOS.xcscheme b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON iOS.xcscheme index 35f18d98..f4d10cb9 100644 --- a/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON iOS.xcscheme +++ b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON iOS.xcscheme @@ -1,6 +1,6 @@ @@ -29,8 +29,8 @@ @@ -47,8 +47,8 @@ @@ -58,7 +58,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "9C7DFC5A1A9102BD005AA3F7" BuildableName = "SwiftyJSON.framework" - BlueprintName = "SwiftyJSON OSX" + BlueprintName = "SwiftyJSON macOS" ReferencedContainer = "container:SwiftyJSON.xcodeproj"> @@ -80,7 +80,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "9C7DFC5A1A9102BD005AA3F7" BuildableName = "SwiftyJSON.framework" - BlueprintName = "SwiftyJSON OSX" + BlueprintName = "SwiftyJSON macOS" ReferencedContainer = "container:SwiftyJSON.xcodeproj"> @@ -98,7 +98,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "9C7DFC5A1A9102BD005AA3F7" BuildableName = "SwiftyJSON.framework" - BlueprintName = "SwiftyJSON OSX" + BlueprintName = "SwiftyJSON macOS" ReferencedContainer = "container:SwiftyJSON.xcodeproj"> diff --git a/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme index 083c1710..c7c55338 100644 --- a/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme +++ b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme @@ -1,6 +1,6 @@ + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Tests/SwiftyJSONTests/Info-iOS.plist b/Tests/Info-iOS.plist similarity index 100% rename from Tests/SwiftyJSONTests/Info-iOS.plist rename to Tests/Info-iOS.plist diff --git a/Tests/SwiftyJSONTests/Info-OSX.plist b/Tests/Info-macOS.plist similarity index 100% rename from Tests/SwiftyJSONTests/Info-OSX.plist rename to Tests/Info-macOS.plist diff --git a/Tests/SwiftyJSONTests/Info-tvOS.plist b/Tests/Info-tvOS.plist similarity index 100% rename from Tests/SwiftyJSONTests/Info-tvOS.plist rename to Tests/Info-tvOS.plist diff --git a/Tests/SwiftyJSONTests/ArrayTests.swift b/Tests/SwiftJSONTests/ArrayTests.swift similarity index 95% rename from Tests/SwiftyJSONTests/ArrayTests.swift rename to Tests/SwiftJSONTests/ArrayTests.swift index c3c53de3..0c955e7d 100644 --- a/Tests/SwiftyJSONTests/ArrayTests.swift +++ b/Tests/SwiftJSONTests/ArrayTests.swift @@ -26,7 +26,7 @@ import SwiftyJSON class ArrayTests: XCTestCase { func testSingleDimensionalArraysGetter() { - let array = ["1","2", "a", "B", "D"] + let array = ["1", "2", "a", "B", "D"] let json = JSON(array) XCTAssertEqual((json.array![0] as JSON).string!, "1") XCTAssertEqual((json.array![1] as JSON).string!, "2") @@ -34,9 +34,9 @@ class ArrayTests: XCTestCase { XCTAssertEqual((json.array![3] as JSON).string!, "B") XCTAssertEqual((json.array![4] as JSON).string!, "D") } - + func testSingleDimensionalArraysSetter() { - let array = ["1","2", "a", "B", "D"] + let array = ["1", "2", "a", "B", "D"] var json = JSON(array) json.arrayObject = ["111", "222"] XCTAssertEqual((json.array![0] as JSON).string!, "111") diff --git a/Tests/SwiftyJSONTests/BaseTests.swift b/Tests/SwiftJSONTests/BaseTests.swift similarity index 66% rename from Tests/SwiftyJSONTests/BaseTests.swift rename to Tests/SwiftJSONTests/BaseTests.swift index 0c0ff8e5..8bbebcde 100644 --- a/Tests/SwiftyJSONTests/BaseTests.swift +++ b/Tests/SwiftJSONTests/BaseTests.swift @@ -21,32 +21,40 @@ // THE SOFTWARE. import XCTest -@testable import SwiftyJSON +import SwiftyJSON class BaseTests: XCTestCase { var testData: Data! - + override func setUp() { - + super.setUp() - - if let file = Bundle(for:BaseTests.self).path(forResource: "Tests", ofType: "json") { - self.testData = try? Data(contentsOf: URL(fileURLWithPath: file)) + + #if SWIFT_PACKAGE + let testBundle = Bundle.module + #else + let testBundle = Bundle(for: BaseTests.self) + #endif + if let file = testBundle.url(forResource: "Tests", withExtension: "json") { + self.testData = try? Data(contentsOf: file) } else { XCTFail("Can't find the test JSON file") } } - + override func tearDown() { super.tearDown() } - + func testInit() { - let json0 = JSON(data:self.testData) + guard let json0 = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } XCTAssertEqual(json0.array!.count, 3) XCTAssertEqual(JSON("123").description, "123") - XCTAssertEqual(JSON(["1":"2"])["1"].string!, "2") + XCTAssertEqual(JSON(["1": "2"])["1"].string!, "2") let dictionary = NSMutableDictionary() dictionary.setObject(NSNumber(value: 1.0), forKey: "number" as NSString) dictionary.setObject(NSNull(), forKey: "null" as NSString) @@ -58,26 +66,30 @@ class BaseTests: XCTestCase { } catch _ { } } - + func testCompare() { XCTAssertNotEqual(JSON("32.1234567890"), JSON(32.1234567890)) - let veryLargeNumber:UInt64 = 9876543210987654321 - XCTAssertNotEqual(JSON("9876543210987654321"),JSON(NSNumber(value:veryLargeNumber))) + let veryLargeNumber: UInt64 = 9876543210987654321 + XCTAssertNotEqual(JSON("9876543210987654321"), JSON(NSNumber(value: veryLargeNumber))) XCTAssertNotEqual(JSON("9876543210987654321.12345678901234567890"), JSON(9876543210987654321.12345678901234567890)) XCTAssertEqual(JSON("😊"), JSON("😊")) XCTAssertNotEqual(JSON("😱"), JSON("😁")) - XCTAssertEqual(JSON([123,321,456]), JSON([123,321,456])) - XCTAssertNotEqual(JSON([123,321,456]), JSON(123456789)) - XCTAssertNotEqual(JSON([123,321,456]), JSON("string")) - XCTAssertNotEqual(JSON(["1":123,"2":321,"3":456]), JSON("string")) - XCTAssertEqual(JSON(["1":123,"2":321,"3":456]), JSON(["2":321,"1":123,"3":456])) - XCTAssertEqual(JSON(NSNull()),JSON(NSNull())) + XCTAssertEqual(JSON([123, 321, 456]), JSON([123, 321, 456])) + XCTAssertNotEqual(JSON([123, 321, 456]), JSON(123456789)) + XCTAssertNotEqual(JSON([123, 321, 456]), JSON("string")) + XCTAssertNotEqual(JSON(["1": 123, "2": 321, "3": 456]), JSON("string")) + XCTAssertEqual(JSON(["1": 123, "2": 321, "3": 456]), JSON(["2": 321, "1": 123, "3": 456])) + XCTAssertEqual(JSON(NSNull()), JSON(NSNull())) XCTAssertNotEqual(JSON(NSNull()), JSON(123)) } - + func testJSONDoesProduceValidWithCorrectKeyPath() { - let json = JSON(data:self.testData) - + + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + let tweets = json let tweets_array = json.array let tweets_1 = json[1] @@ -89,12 +101,12 @@ class BaseTests: XCTestCase { XCTAssertNotEqual(tweets_1.type, Type.null) XCTAssertEqual(tweets_1_user_name, JSON("Raffi Krikorian")) XCTAssertEqual(tweets_1_user_name_string!, "Raffi Krikorian") - + let tweets_1_coordinates = tweets_1["coordinates"] let tweets_1_coordinates_coordinates = tweets_1_coordinates["coordinates"] let tweets_1_coordinates_coordinates_point_0_double = tweets_1_coordinates_coordinates[0].double let tweets_1_coordinates_coordinates_point_1_float = tweets_1_coordinates_coordinates[1].float - let new_tweets_1_coordinates_coordinates = JSON([-122.25831,37.871609] as NSArray) + let new_tweets_1_coordinates_coordinates = JSON([-122.25831, 37.871609] as NSArray) XCTAssertEqual(tweets_1_coordinates_coordinates, new_tweets_1_coordinates_coordinates) XCTAssertEqual(tweets_1_coordinates_coordinates_point_0_double!, -122.25831) XCTAssertTrue(tweets_1_coordinates_coordinates_point_1_float! == 37.871609) @@ -106,16 +118,16 @@ class BaseTests: XCTestCase { let tweets_1_coordinates_coordinates_point_1 = tweets_1_coordinates_coordinates[1] XCTAssertEqual(tweets_1_coordinates_coordinates_point_0, JSON(-122.25831)) XCTAssertEqual(tweets_1_coordinates_coordinates_point_1, JSON(37.871609)) - + let created_at = json[0]["created_at"].string let id_str = json[0]["id_str"].string let favorited = json[0]["favorited"].bool let id = json[0]["id"].int64 let in_reply_to_user_id_str = json[0]["in_reply_to_user_id_str"] XCTAssertEqual(created_at!, "Tue Aug 28 21:16:23 +0000 2012") - XCTAssertEqual(id_str!,"240558470661799936") + XCTAssertEqual(id_str!, "240558470661799936") XCTAssertFalse(favorited!) - XCTAssertEqual(id!,240558470661799936) + XCTAssertEqual(id!, 240558470661799936) XCTAssertEqual(in_reply_to_user_id_str.type, Type.null) let user = json[0]["user"] @@ -130,7 +142,7 @@ class BaseTests: XCTestCase { XCTAssert(user_dictionary_name == "OAuth Dancer") XCTAssert(user_dictionary_name_profile_image_url == URL(string: "http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg")) } - + func testJSONNumberCompare() { XCTAssertEqual(JSON(12376352.123321), JSON(12376352.123321)) XCTAssertGreaterThan(JSON(20.211), JSON(20.112)) @@ -139,7 +151,7 @@ class BaseTests: XCTestCase { XCTAssertLessThan(JSON(-82320.211), JSON(20.112)) XCTAssertLessThanOrEqual(JSON(-320.211), JSON(123.1)) XCTAssertLessThanOrEqual(JSON(-8763), JSON(-8763)) - + XCTAssertEqual(JSON(12376352.123321), JSON(12376352.123321)) XCTAssertGreaterThan(JSON(20.211), JSON(20.112)) XCTAssertGreaterThanOrEqual(JSON(30.211), JSON(20.112)) @@ -149,116 +161,120 @@ class BaseTests: XCTestCase { XCTAssertLessThanOrEqual(JSON(-8763), JSON(-8763)) } - func testNumberConvertToString(){ + func testNumberConvertToString() { XCTAssertEqual(JSON(true).stringValue, "true") XCTAssertEqual(JSON(999.9823).stringValue, "999.9823") XCTAssertEqual(JSON(true).number!.stringValue, "1") XCTAssertEqual(JSON(false).number!.stringValue, "0") XCTAssertEqual(JSON("hello").numberValue.stringValue, "0") XCTAssertEqual(JSON(NSNull()).numberValue.stringValue, "0") - XCTAssertEqual(JSON(["a","b","c","d"]).numberValue.stringValue, "0") - XCTAssertEqual(JSON(["a":"b","c":"d"]).numberValue.stringValue, "0") + XCTAssertEqual(JSON(["a", "b", "c", "d"]).numberValue.stringValue, "0") + XCTAssertEqual(JSON(["a": "b", "c": "d"]).numberValue.stringValue, "0") } - - func testNumberPrint(){ - XCTAssertEqual(JSON(false).description,"false") - XCTAssertEqual(JSON(true).description,"true") + func testNumberPrint() { + + XCTAssertEqual(JSON(false).description, "false") + XCTAssertEqual(JSON(true).description, "true") - XCTAssertEqual(JSON(1).description,"1") - XCTAssertEqual(JSON(22).description,"22") + XCTAssertEqual(JSON(1).description, "1") + XCTAssertEqual(JSON(22).description, "22") #if (arch(x86_64) || arch(arm64)) - XCTAssertEqual(JSON(9.22337203685478E18).description,"9.22337203685478e+18") + XCTAssertEqual(JSON(9.22337203685478E18).description, "9.22337203685478e+18") #elseif (arch(i386) || arch(arm)) - XCTAssertEqual(JSON(2147483647).description,"2147483647") + XCTAssertEqual(JSON(2147483647).description, "2147483647") #endif - XCTAssertEqual(JSON(-1).description,"-1") - XCTAssertEqual(JSON(-934834834).description,"-934834834") - XCTAssertEqual(JSON(-2147483648).description,"-2147483648") - - XCTAssertEqual(JSON(1.5555).description,"1.5555") - XCTAssertEqual(JSON(-9.123456789).description,"-9.123456789") - XCTAssertEqual(JSON(-0.00000000000000001).description,"-1e-17") - XCTAssertEqual(JSON(-999999999999999999999999.000000000000000000000001).description,"-1e+24") - XCTAssertEqual(JSON(-9999999991999999999999999.88888883433343439438493483483943948341).stringValue,"-9.999999991999999e+24") - - XCTAssertEqual(JSON(Int(Int.max)).description,"\(Int.max)") - XCTAssertEqual(JSON(NSNumber(value: Int.min)).description,"\(Int.min)") - XCTAssertEqual(JSON(NSNumber(value: UInt.max)).description,"\(UInt.max)") - XCTAssertEqual(JSON(NSNumber(value: UInt64.max)).description,"\(UInt64.max)") - XCTAssertEqual(JSON(NSNumber(value: Int64.max)).description,"\(Int64.max)") - XCTAssertEqual(JSON(NSNumber(value: UInt64.max)).description,"\(UInt64.max)") - - XCTAssertEqual(JSON(Double.infinity).description,"inf") - XCTAssertEqual(JSON(-Double.infinity).description,"-inf") - XCTAssertEqual(JSON(Double.nan).description,"nan") - - XCTAssertEqual(JSON(1.0/0.0).description,"inf") - XCTAssertEqual(JSON(-1.0/0.0).description,"-inf") - XCTAssertEqual(JSON(0.0/0.0).description,"nan") + XCTAssertEqual(JSON(-1).description, "-1") + XCTAssertEqual(JSON(-934834834).description, "-934834834") + XCTAssertEqual(JSON(-2147483648).description, "-2147483648") + + XCTAssertEqual(JSON(1.5555).description, "1.5555") + XCTAssertEqual(JSON(-9.123456789).description, "-9.123456789") + XCTAssertEqual(JSON(-0.00000000000000001).description, "-1e-17") + XCTAssertEqual(JSON(-999999999999999999999999.000000000000000000000001).description, "-1e+24") + XCTAssertEqual(JSON(-9999999991999999999999999.88888883433343439438493483483943948341).stringValue, "-9.999999991999999e+24") + + XCTAssertEqual(JSON(Int(Int.max)).description, "\(Int.max)") + XCTAssertEqual(JSON(NSNumber(value: Int.min)).description, "\(Int.min)") + XCTAssertEqual(JSON(NSNumber(value: UInt.max)).description, "\(UInt.max)") + XCTAssertEqual(JSON(NSNumber(value: UInt64.max)).description, "\(UInt64.max)") + XCTAssertEqual(JSON(NSNumber(value: Int64.max)).description, "\(Int64.max)") + XCTAssertEqual(JSON(NSNumber(value: UInt64.max)).description, "\(UInt64.max)") + + XCTAssertEqual(JSON(Double.infinity).description, "inf") + XCTAssertEqual(JSON(-Double.infinity).description, "-inf") + XCTAssertEqual(JSON(Double.nan).description, "nan") + + XCTAssertEqual(JSON(1.0/0.0).description, "inf") + XCTAssertEqual(JSON(-1.0/0.0).description, "-inf") + XCTAssertEqual(JSON(0.0/0.0).description, "nan") } - + func testNullJSON() { - XCTAssertEqual(JSON(NSNull()).debugDescription,"null") - - let json:JSON = JSON.null - XCTAssertEqual(json.debugDescription,"null") + XCTAssertEqual(JSON(NSNull()).debugDescription, "null") + + let json: JSON = JSON.null + XCTAssertEqual(json.debugDescription, "null") XCTAssertNil(json.error) - let json1:JSON = JSON(NSNull()) + let json1: JSON = JSON(NSNull()) if json1 != JSON.null { XCTFail("json1 should be nil") } } - + func testExistance() { - let dictionary = ["number":1111] + let dictionary = ["number": 1111] let json = JSON(dictionary) XCTAssertFalse(json["unspecifiedValue"].exists()) XCTAssertFalse(json[0].exists()) XCTAssertTrue(json["number"].exists()) - let array = [["number":1111]] + let array = [["number": 1111]] let jsonForArray = JSON(array) XCTAssertTrue(jsonForArray[0].exists()) XCTAssertFalse(jsonForArray[1].exists()) XCTAssertFalse(jsonForArray["someValue"].exists()) } - + func testErrorHandle() { - let json = JSON(data:self.testData) - if let _ = json["wrong-type"].string { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + if json["wrong-type"].string != nil { XCTFail("Should not run into here") } else { - XCTAssertEqual(json["wrong-type"].error!.code, SwiftyJSON.ErrorWrongType) + XCTAssertEqual(json["wrong-type"].error, SwiftyJSONError.wrongType) } - if let _ = json[0]["not-exist"].string { + if json[0]["not-exist"].string != nil { XCTFail("Should not run into here") } else { - XCTAssertEqual(json[0]["not-exist"].error!.code, SwiftyJSON.ErrorNotExist) + XCTAssertEqual(json[0]["not-exist"].error, SwiftyJSONError.notExist) } - + let wrongJSON = JSON(NSObject()) if let error = wrongJSON.error { - XCTAssertEqual(error.code, SwiftyJSON.ErrorUnsupportedType) + XCTAssertEqual(error, SwiftyJSONError.unsupportedType) } } - + func testReturnObject() { - let json = JSON(data:self.testData) + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } XCTAssertNotNil(json.object) } - - func testNumberCompare(){ - XCTAssertEqual(NSNumber(value: 888332), NSNumber(value:888332)) - XCTAssertNotEqual(NSNumber(value: 888332.1), NSNumber(value:888332)) - XCTAssertLessThan(NSNumber(value: 888332).doubleValue, NSNumber(value:888332.1).doubleValue) - XCTAssertGreaterThan(NSNumber(value: 888332.1).doubleValue, NSNumber(value:888332).doubleValue) - XCTAssertFalse(NSNumber(value: 1) == NSNumber(value:true)) - XCTAssertFalse(NSNumber(value: 0) == NSNumber(value:false)) - XCTAssertEqual(NSNumber(value: false), NSNumber(value:false)) - XCTAssertEqual(NSNumber(value: true), NSNumber(value:true)) - } - + func testErrorThrowing() { + let invalidJson = "{\"foo\": 300]" // deliberately incorrect JSON + let invalidData = invalidJson.data(using: .utf8)! + do { + _ = try JSON(data: invalidData) + XCTFail("Should have thrown error; we should not have gotten here") + } catch { + // everything is OK + } + } } diff --git a/Tests/SwiftJSONTests/CodableTests.swift b/Tests/SwiftJSONTests/CodableTests.swift new file mode 100644 index 00000000..a3608c1c --- /dev/null +++ b/Tests/SwiftJSONTests/CodableTests.swift @@ -0,0 +1,104 @@ +// CodableTests.swift +// +// Created by Lei Wang on 2018/1/9. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import XCTest +import SwiftyJSON + +class CodableTests: XCTestCase { + + func testEncodeNull() { + var json = JSON([NSNull()]) + _ = try! JSONEncoder().encode(json) + json = JSON([nil]) + _ = try! JSONEncoder().encode(json) + let dictionary: [String: Any?] = ["key": nil] + json = JSON(dictionary) + _ = try! JSONEncoder().encode(json) + } + + func testArrayCodable() { + let jsonString = """ + [1,"false", ["A", 4.3231],"3",true] + """ + var data = jsonString.data(using: .utf8)! + let json = try! JSONDecoder().decode(JSON.self, from: data) + XCTAssertEqual(json.arrayValue.first?.int, 1) + XCTAssertEqual(json[1].bool, nil) + XCTAssertEqual(json[1].string, "false") + XCTAssertEqual(json[3].string, "3") + XCTAssertEqual(json[2][1].double!, 4.3231) + XCTAssertEqual(json.arrayValue[0].bool, nil) + XCTAssertEqual(json.array!.last!.bool, true) + let jsonList = try! JSONDecoder().decode([JSON].self, from: data) + XCTAssertEqual(jsonList.first?.int, 1) + XCTAssertEqual(jsonList.last!.bool, true) + data = try! JSONEncoder().encode(json) + let list = try! JSONSerialization.jsonObject(with: data, options: []) as! [Any] + XCTAssertEqual(list[0] as! Int, 1) + XCTAssertEqual((list[2] as! [Any])[1] as! NSNumber, 4.3231) + } + + func testDictionaryCodable() { + let dictionary: [String: Any] = ["number": 9823.212, "name": "NAME", "list": [1234, 4.21223256], "object": ["sub_number": 877.2323, "sub_name": "sub_name"], "bool": true] + var data = try! JSONSerialization.data(withJSONObject: dictionary, options: []) + let json = try! JSONDecoder().decode(JSON.self, from: data) + XCTAssertNotNil(json.dictionary) + XCTAssertEqual(json["number"].float, 9823.212) + XCTAssertEqual(json["list"].arrayObject is [NSNumber], true) + XCTAssertEqual(json["object"]["sub_number"].float, 877.2323) + XCTAssertEqual(json["bool"].bool, true) + let jsonDict = try! JSONDecoder().decode([String: JSON].self, from: data) + XCTAssertEqual(jsonDict["number"]?.int, 9823) + XCTAssertEqual(jsonDict["object"]?["sub_name"], "sub_name") + data = try! JSONEncoder().encode(json) + var encoderDict = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] + XCTAssertEqual(encoderDict["list"] as! [NSNumber], [1234, 4.21223256]) + XCTAssertEqual(encoderDict["bool"] as! Bool, true) + data = try! JSONEncoder().encode(jsonDict) + encoderDict = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] + XCTAssertEqual(encoderDict["name"] as! String, dictionary["name"] as! String) + XCTAssertEqual((encoderDict["object"] as! [String: Any])["sub_number"] as! NSNumber, 877.2323) + } + + func testCodableModel() { + let dictionary: [String: Any] = [ + "number": 9823.212, + "name": "NAME", + "list": [1234, 4.21223256], + "object": ["sub_number": 877.2323, "sub_name": "sub_name"], + "bool": true] + let data = try! JSONSerialization.data(withJSONObject: dictionary, options: []) + let model = try! JSONDecoder().decode(CodableModel.self, from: data) + XCTAssertEqual(model.subName, "sub_name") + } +} + +private struct CodableModel: Codable { + let name: String + let number: Double + let bool: Bool + let list: [Double] + private let object: JSON + var subName: String? { + return object["sub_name"].string + } +} diff --git a/Tests/SwiftyJSONTests/ComparableTests.swift b/Tests/SwiftJSONTests/ComparableTests.swift similarity index 59% rename from Tests/SwiftyJSONTests/ComparableTests.swift rename to Tests/SwiftJSONTests/ComparableTests.swift index f238012f..a7b69086 100644 --- a/Tests/SwiftyJSONTests/ComparableTests.swift +++ b/Tests/SwiftJSONTests/ComparableTests.swift @@ -26,279 +26,278 @@ import SwiftyJSON class ComparableTests: XCTestCase { func testNumberEqual() { - let jsonL1:JSON = 1234567890.876623 - let jsonR1:JSON = JSON(1234567890.876623) + let jsonL1: JSON = 1234567890.876623 + let jsonR1: JSON = JSON(1234567890.876623) XCTAssertEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 == 1234567890.876623) - let jsonL2:JSON = 987654321 - let jsonR2:JSON = JSON(987654321) + let jsonL2: JSON = 987654321 + let jsonR2: JSON = JSON(987654321) XCTAssertEqual(jsonL2, jsonR2) XCTAssertTrue(jsonR2 == 987654321) - - let jsonL3:JSON = JSON(NSNumber(value:87654321.12345678)) - let jsonR3:JSON = JSON(NSNumber(value:87654321.12345678)) + let jsonL3: JSON = JSON(NSNumber(value: 87654321.12345678)) + let jsonR3: JSON = JSON(NSNumber(value: 87654321.12345678)) XCTAssertEqual(jsonL3, jsonR3) XCTAssertTrue(jsonR3 == 87654321.12345678) } - + func testNumberNotEqual() { - let jsonL1:JSON = 1234567890.876623 - let jsonR1:JSON = JSON(123.123) + let jsonL1: JSON = 1234567890.876623 + let jsonR1: JSON = JSON(123.123) XCTAssertNotEqual(jsonL1, jsonR1) XCTAssertFalse(jsonL1 == 34343) - - let jsonL2:JSON = 8773 - let jsonR2:JSON = JSON(123.23) + + let jsonL2: JSON = 8773 + let jsonR2: JSON = JSON(123.23) XCTAssertNotEqual(jsonL2, jsonR2) XCTAssertFalse(jsonR1 == 454352) - - let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) - let jsonR3:JSON = JSON(NSNumber(value:87654321.45678)) + + let jsonL3: JSON = JSON(NSNumber(value: 87621.12345678)) + let jsonR3: JSON = JSON(NSNumber(value: 87654321.45678)) XCTAssertNotEqual(jsonL3, jsonR3) XCTAssertFalse(jsonL3 == 4545.232) } - + func testNumberGreaterThanOrEqual() { - let jsonL1:JSON = 1234567890.876623 - let jsonR1:JSON = JSON(123.123) + let jsonL1: JSON = 1234567890.876623 + let jsonR1: JSON = JSON(123.123) XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 >= -37434) - - let jsonL2:JSON = 8773 - let jsonR2:JSON = JSON(-87343) + + let jsonL2: JSON = 8773 + let jsonR2: JSON = JSON(-87343) XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) XCTAssertTrue(jsonR2 >= -988343) - let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) - let jsonR3:JSON = JSON(NSNumber(value:87621.12345678)) + let jsonL3: JSON = JSON(NSNumber(value: 87621.12345678)) + let jsonR3: JSON = JSON(NSNumber(value: 87621.12345678)) XCTAssertGreaterThanOrEqual(jsonL3, jsonR3) XCTAssertTrue(jsonR3 >= 0.3232) } - + func testNumberLessThanOrEqual() { - let jsonL1:JSON = 1234567890.876623 - let jsonR1:JSON = JSON(123.123) + let jsonL1: JSON = 1234567890.876623 + let jsonR1: JSON = JSON(123.123) XCTAssertLessThanOrEqual(jsonR1, jsonL1) XCTAssertFalse(83487343.3493 <= jsonR1) - - let jsonL2:JSON = 8773 - let jsonR2:JSON = JSON(-123.23) + + let jsonL2: JSON = 8773 + let jsonR2: JSON = JSON(-123.23) XCTAssertLessThanOrEqual(jsonR2, jsonL2) XCTAssertFalse(9348343 <= jsonR2) - - let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) - let jsonR3:JSON = JSON(NSNumber(value:87621.12345678)) + + let jsonL3: JSON = JSON(NSNumber(value: 87621.12345678)) + let jsonR3: JSON = JSON(NSNumber(value: 87621.12345678)) XCTAssertLessThanOrEqual(jsonR3, jsonL3) XCTAssertTrue(87621.12345678 <= jsonR3) } func testNumberGreaterThan() { - let jsonL1:JSON = 1234567890.876623 - let jsonR1:JSON = JSON(123.123) + let jsonL1: JSON = 1234567890.876623 + let jsonR1: JSON = JSON(123.123) XCTAssertGreaterThan(jsonL1, jsonR1) XCTAssertFalse(jsonR1 > 192388843.0988) - let jsonL2:JSON = 8773 - let jsonR2:JSON = JSON(123.23) + let jsonL2: JSON = 8773 + let jsonR2: JSON = JSON(123.23) XCTAssertGreaterThan(jsonL2, jsonR2) XCTAssertFalse(jsonR2 > 877434) - let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) - let jsonR3:JSON = JSON(NSNumber(value:87621.1234567)) + let jsonL3: JSON = JSON(NSNumber(value: 87621.12345678)) + let jsonR3: JSON = JSON(NSNumber(value: 87621.1234567)) XCTAssertGreaterThan(jsonL3, jsonR3) XCTAssertFalse(-7799 > jsonR3) } - + func testNumberLessThan() { - let jsonL1:JSON = 1234567890.876623 - let jsonR1:JSON = JSON(123.123) + let jsonL1: JSON = 1234567890.876623 + let jsonR1: JSON = JSON(123.123) XCTAssertLessThan(jsonR1, jsonL1) XCTAssertTrue(jsonR1 < 192388843.0988) - let jsonL2:JSON = 8773 - let jsonR2:JSON = JSON(123.23) + let jsonL2: JSON = 8773 + let jsonR2: JSON = JSON(123.23) XCTAssertLessThan(jsonR2, jsonL2) XCTAssertTrue(jsonR2 < 877434) - - let jsonL3:JSON = JSON(NSNumber(value:87621.12345678)) - let jsonR3:JSON = JSON(NSNumber(value:87621.1234567)) + + let jsonL3: JSON = JSON(NSNumber(value: 87621.12345678)) + let jsonR3: JSON = JSON(NSNumber(value: 87621.1234567)) XCTAssertLessThan(jsonR3, jsonL3) XCTAssertTrue(-7799 < jsonR3) } func testBoolEqual() { - let jsonL1:JSON = true - let jsonR1:JSON = JSON(true) + let jsonL1: JSON = true + let jsonR1: JSON = JSON(true) XCTAssertEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 == true) - let jsonL2:JSON = false - let jsonR2:JSON = JSON(false) + let jsonL2: JSON = false + let jsonR2: JSON = JSON(false) XCTAssertEqual(jsonL2, jsonR2) XCTAssertTrue(jsonL2 == false) } - + func testBoolNotEqual() { - let jsonL1:JSON = true - let jsonR1:JSON = JSON(false) + let jsonL1: JSON = true + let jsonR1: JSON = JSON(false) XCTAssertNotEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 != false) - let jsonL2:JSON = false - let jsonR2:JSON = JSON(true) + let jsonL2: JSON = false + let jsonR2: JSON = JSON(true) XCTAssertNotEqual(jsonL2, jsonR2) XCTAssertTrue(jsonL2 != true) } - + func testBoolGreaterThanOrEqual() { - let jsonL1:JSON = true - let jsonR1:JSON = JSON(true) + let jsonL1: JSON = true + let jsonR1: JSON = JSON(true) XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 >= true) - - let jsonL2:JSON = false - let jsonR2:JSON = JSON(false) + + let jsonL2: JSON = false + let jsonR2: JSON = JSON(false) XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) XCTAssertFalse(jsonL2 >= true) } - + func testBoolLessThanOrEqual() { - let jsonL1:JSON = true - let jsonR1:JSON = JSON(true) + let jsonL1: JSON = true + let jsonR1: JSON = JSON(true) XCTAssertLessThanOrEqual(jsonL1, jsonR1) XCTAssertTrue(true <= jsonR1) - - let jsonL2:JSON = false - let jsonR2:JSON = JSON(false) + + let jsonL2: JSON = false + let jsonR2: JSON = JSON(false) XCTAssertLessThanOrEqual(jsonL2, jsonR2) XCTAssertFalse(jsonL2 <= true) } - + func testBoolGreaterThan() { - let jsonL1:JSON = true - let jsonR1:JSON = JSON(true) + let jsonL1: JSON = true + let jsonR1: JSON = JSON(true) XCTAssertFalse(jsonL1 > jsonR1) XCTAssertFalse(jsonL1 > true) XCTAssertFalse(jsonR1 > false) - let jsonL2:JSON = false - let jsonR2:JSON = JSON(false) + let jsonL2: JSON = false + let jsonR2: JSON = JSON(false) XCTAssertFalse(jsonL2 > jsonR2) XCTAssertFalse(jsonL2 > false) XCTAssertFalse(jsonR2 > true) - let jsonL3:JSON = true - let jsonR3:JSON = JSON(false) + let jsonL3: JSON = true + let jsonR3: JSON = JSON(false) XCTAssertFalse(jsonL3 > jsonR3) XCTAssertFalse(jsonL3 > false) XCTAssertFalse(jsonR3 > true) - - let jsonL4:JSON = false - let jsonR4:JSON = JSON(true) + + let jsonL4: JSON = false + let jsonR4: JSON = JSON(true) XCTAssertFalse(jsonL4 > jsonR4) XCTAssertFalse(jsonL4 > false) XCTAssertFalse(jsonR4 > true) } - + func testBoolLessThan() { - let jsonL1:JSON = true - let jsonR1:JSON = JSON(true) + let jsonL1: JSON = true + let jsonR1: JSON = JSON(true) XCTAssertFalse(jsonL1 < jsonR1) XCTAssertFalse(jsonL1 < true) XCTAssertFalse(jsonR1 < false) - let jsonL2:JSON = false - let jsonR2:JSON = JSON(false) + let jsonL2: JSON = false + let jsonR2: JSON = JSON(false) XCTAssertFalse(jsonL2 < jsonR2) XCTAssertFalse(jsonL2 < false) XCTAssertFalse(jsonR2 < true) - - let jsonL3:JSON = true - let jsonR3:JSON = JSON(false) + + let jsonL3: JSON = true + let jsonR3: JSON = JSON(false) XCTAssertFalse(jsonL3 < jsonR3) XCTAssertFalse(jsonL3 < false) XCTAssertFalse(jsonR3 < true) - let jsonL4:JSON = false - let jsonR4:JSON = JSON(true) + let jsonL4: JSON = false + let jsonR4: JSON = JSON(true) XCTAssertFalse(jsonL4 < jsonR4) XCTAssertFalse(jsonL4 < false) XCTAssertFalse(true < jsonR4) } - + func testStringEqual() { - let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" - let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") + let jsonL1: JSON = "abcdefg 123456789 !@#$%^&*()" + let jsonR1: JSON = JSON("abcdefg 123456789 !@#$%^&*()") XCTAssertEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 == "abcdefg 123456789 !@#$%^&*()") } - + func testStringNotEqual() { - let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" - let jsonR1:JSON = JSON("-=[]\\\"987654321") - + let jsonL1: JSON = "abcdefg 123456789 !@#$%^&*()" + let jsonR1: JSON = JSON("-=[]\\\"987654321") + XCTAssertNotEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 != "not equal") } - + func testStringGreaterThanOrEqual() { - let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" - let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") - + let jsonL1: JSON = "abcdefg 123456789 !@#$%^&*()" + let jsonR1: JSON = JSON("abcdefg 123456789 !@#$%^&*()") + XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 >= "abcdefg 123456789 !@#$%^&*()") - let jsonL2:JSON = "z-+{}:" - let jsonR2:JSON = JSON("a<>?:") + let jsonL2: JSON = "z-+{}:" + let jsonR2: JSON = JSON("a<>?:") XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) XCTAssertTrue(jsonL2 >= "mnbvcxz") } - + func testStringLessThanOrEqual() { - let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" - let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") - + let jsonL1: JSON = "abcdefg 123456789 !@#$%^&*()" + let jsonR1: JSON = JSON("abcdefg 123456789 !@#$%^&*()") + XCTAssertLessThanOrEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 <= "abcdefg 123456789 !@#$%^&*()") - - let jsonL2:JSON = "z-+{}:" - let jsonR2:JSON = JSON("a<>?:") + + let jsonL2: JSON = "z-+{}:" + let jsonR2: JSON = JSON("a<>?:") XCTAssertLessThanOrEqual(jsonR2, jsonL2) XCTAssertTrue("mnbvcxz" <= jsonL2) } - + func testStringGreaterThan() { - let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" - let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") - + let jsonL1: JSON = "abcdefg 123456789 !@#$%^&*()" + let jsonR1: JSON = JSON("abcdefg 123456789 !@#$%^&*()") + XCTAssertFalse(jsonL1 > jsonR1) XCTAssertFalse(jsonL1 > "abcdefg 123456789 !@#$%^&*()") - - let jsonL2:JSON = "z-+{}:" - let jsonR2:JSON = JSON("a<>?:") + + let jsonL2: JSON = "z-+{}:" + let jsonR2: JSON = JSON("a<>?:") XCTAssertGreaterThan(jsonL2, jsonR2) XCTAssertFalse("87663434" > jsonL2) } func testStringLessThan() { - let jsonL1:JSON = "abcdefg 123456789 !@#$%^&*()" - let jsonR1:JSON = JSON("abcdefg 123456789 !@#$%^&*()") - + let jsonL1: JSON = "abcdefg 123456789 !@#$%^&*()" + let jsonR1: JSON = JSON("abcdefg 123456789 !@#$%^&*()") + XCTAssertFalse(jsonL1 < jsonR1) XCTAssertFalse(jsonL1 < "abcdefg 123456789 !@#$%^&*()") - - let jsonL2:JSON = "98774" - let jsonR2:JSON = JSON("123456") + + let jsonL2: JSON = "98774" + let jsonR2: JSON = JSON("123456") XCTAssertLessThan(jsonR2, jsonL2) XCTAssertFalse(jsonL2 < "09") } func testNil() { - let jsonL1:JSON = JSON.null - let jsonR1:JSON = JSON(NSNull()) + let jsonL1: JSON = JSON.null + let jsonR1: JSON = JSON(NSNull()) XCTAssertEqual(jsonL1, jsonR1) XCTAssertTrue(jsonL1 != "123") XCTAssertFalse(jsonL1 > "abcd") @@ -308,31 +307,31 @@ class ComparableTests: XCTestCase { XCTAssertTrue(jsonL1 >= jsonR1) XCTAssertTrue(jsonL1 <= jsonR1) } - + func testArray() { - let jsonL1:JSON = [1,2,"4",5,"6"] - let jsonR1:JSON = JSON([1,2,"4",5,"6"]) + let jsonL1: JSON = [1, 2, "4", 5, "6"] + let jsonR1: JSON = JSON([1, 2, "4", 5, "6"]) XCTAssertEqual(jsonL1, jsonR1) - XCTAssertTrue(jsonL1 == [1,2,"4",5,"6"]) - XCTAssertTrue(jsonL1 != ["abcd","efg"]) + XCTAssertTrue(jsonL1 == [1, 2, "4", 5, "6"]) + XCTAssertTrue(jsonL1 != ["abcd", "efg"]) XCTAssertTrue(jsonL1 >= jsonR1) XCTAssertTrue(jsonL1 <= jsonR1) - XCTAssertFalse(jsonL1 > ["abcd",""]) + XCTAssertFalse(jsonL1 > ["abcd", ""]) XCTAssertFalse(jsonR1 < []) XCTAssertFalse(jsonL1 >= [:]) } - + func testDictionary() { - let jsonL1:JSON = ["2": 2, "name": "Jack", "List": ["a", 1.09, NSNull()]] - let jsonR1:JSON = JSON(["2": 2, "name": "Jack", "List": ["a", 1.09, NSNull()]]) - + let jsonL1: JSON = ["2": 2, "name": "Jack", "List": ["a", 1.09, NSNull()]] + let jsonR1: JSON = JSON(["2": 2, "name": "Jack", "List": ["a", 1.09, NSNull()]]) + XCTAssertEqual(jsonL1, jsonR1) - XCTAssertTrue(jsonL1 != ["1":2,"Hello":"World","Koo":"Foo"]) + XCTAssertTrue(jsonL1 != ["1": 2, "Hello": "World", "Koo": "Foo"]) XCTAssertTrue(jsonL1 >= jsonR1) XCTAssertTrue(jsonL1 <= jsonR1) XCTAssertFalse(jsonL1 >= [:]) - XCTAssertFalse(jsonR1 <= ["999":"aaaa"]) - XCTAssertFalse(jsonL1 > [")(*&^":1234567]) - XCTAssertFalse(jsonR1 < ["MNHH":"JUYTR"]) + XCTAssertFalse(jsonR1 <= ["999": "aaaa"]) + XCTAssertFalse(jsonL1 > [")(*&^": 1234567]) + XCTAssertFalse(jsonR1 < ["MNHH": "JUYTR"]) } } diff --git a/Tests/SwiftJSONTests/ConcurrencyTests.swift b/Tests/SwiftJSONTests/ConcurrencyTests.swift new file mode 100644 index 00000000..a6eaa099 --- /dev/null +++ b/Tests/SwiftJSONTests/ConcurrencyTests.swift @@ -0,0 +1,89 @@ +// ConcurrencyTests.swift +// +// Copyright (c) 2014 - 2017 Ruoyu Fu, Pinglin Tang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import XCTest +import SwiftyJSON + +/// Tests verifying Sendable conformance for Swift 6 concurrency. +/// Each test targets a specific type made Sendable in this PR. +class ConcurrencyTests: XCTestCase { + + actor Processor { + func extract(_ json: JSON) -> String { + json["name"].stringValue + } + + func extractType(_ json: JSON) -> Type { + json["value"].type + } + + func requireField(_ json: JSON) throws -> String { + guard json["required"].exists() else { + throw SwiftyJSONError.notExist + } + return json["required"].stringValue + } + } + + /// Verifies JSON conforms to Sendable (can cross actor boundary) + func testJSONSendable() async { + let json = JSON(["name": "test", "count": 42]) + let processor = Processor() + + let result = await processor.extract(json) + + XCTAssertEqual(result, "test") + } + + /// Verifies Type enum conforms to Sendable (can be returned across actor boundary) + func testTypeSendable() async { + let processor = Processor() + + let stringType = await processor.extractType(JSON(["value": "hello"])) + let numberType = await processor.extractType(JSON(["value": 123])) + let boolType = await processor.extractType(JSON(["value": true])) + let nullType = await processor.extractType(JSON(["value": NSNull()])) + let arrayType = await processor.extractType(JSON(["value": [1, 2, 3]])) + let dictType = await processor.extractType(JSON(["value": ["nested": "object"]])) + + XCTAssertEqual(stringType, .string) + XCTAssertEqual(numberType, .number) + XCTAssertEqual(boolType, .bool) + XCTAssertEqual(nullType, .null) + XCTAssertEqual(arrayType, .array) + XCTAssertEqual(dictType, .dictionary) + } + + /// Verifies SwiftyJSONError conforms to Sendable (can be thrown across actor boundary) + func testSwiftyJSONErrorSendable() async { + let processor = Processor() + + do { + _ = try await processor.requireField(JSON(["other": "value"])) + XCTFail("Should have thrown") + } catch SwiftyJSONError.notExist { + // Error successfully crossed actor boundary + } catch { + XCTFail("Unexpected error: \(error)") + } + } +} diff --git a/Tests/SwiftyJSONTests/DictionaryTests.swift b/Tests/SwiftJSONTests/DictionaryTests.swift similarity index 84% rename from Tests/SwiftyJSONTests/DictionaryTests.swift rename to Tests/SwiftJSONTests/DictionaryTests.swift index 5f9c822f..dc89200e 100644 --- a/Tests/SwiftyJSONTests/DictionaryTests.swift +++ b/Tests/SwiftJSONTests/DictionaryTests.swift @@ -26,7 +26,7 @@ import SwiftyJSON class DictionaryTests: XCTestCase { func testGetter() { - let dictionary = ["number":9823.212, "name":"NAME", "list":[1234, 4.212], "object":["sub_number":877.2323, "sub_name":"sub_name"], "bool":true] as [String : Any] + let dictionary = ["number": 9823.212, "name": "NAME", "list": [1234, 4.212], "object": ["sub_number": 877.2323, "sub_name": "sub_name"], "bool": true] as [String: Any] let json = JSON(dictionary) //dictionary XCTAssertEqual((json.dictionary!["number"]! as JSON).double!, 9823.212) @@ -45,11 +45,11 @@ class DictionaryTests: XCTestCase { XCTAssertTrue(json.dictionaryObject!["null"] == nil) XCTAssertTrue(JSON.null.dictionaryObject == nil) } - + func testSetter() { - var json:JSON = ["test":"case"] - XCTAssertEqual(json.dictionaryObject! as! [String : String], ["test":"case"]) - json.dictionaryObject = ["name":"NAME"] - XCTAssertEqual(json.dictionaryObject! as! [String : String], ["name":"NAME"]) + var json: JSON = ["test": "case"] + XCTAssertEqual(json.dictionaryObject! as! [String: String], ["test": "case"]) + json.dictionaryObject = ["name": "NAME"] + XCTAssertEqual(json.dictionaryObject! as! [String: String], ["name": "NAME"]) } } diff --git a/Tests/SwiftyJSONTests/LiteralConvertibleTests.swift b/Tests/SwiftJSONTests/LiteralConvertibleTests.swift similarity index 74% rename from Tests/SwiftyJSONTests/LiteralConvertibleTests.swift rename to Tests/SwiftJSONTests/LiteralConvertibleTests.swift index fa88e231..9e478c7b 100644 --- a/Tests/SwiftyJSONTests/LiteralConvertibleTests.swift +++ b/Tests/SwiftJSONTests/LiteralConvertibleTests.swift @@ -26,7 +26,7 @@ import SwiftyJSON class LiteralConvertibleTests: XCTestCase { func testNumber() { - var json:JSON = 1234567890.876623 + var json: JSON = 1234567890.876623 XCTAssertEqual(json.int!, 1234567890) XCTAssertEqual(json.intValue, 1234567890) XCTAssertEqual(json.double!, 1234567890.876623) @@ -34,40 +34,40 @@ class LiteralConvertibleTests: XCTestCase { XCTAssertTrue(json.float! == 1234567890.876623) XCTAssertTrue(json.floatValue == 1234567890.876623) } - + func testBool() { - var jsonTrue:JSON = true + var jsonTrue: JSON = true XCTAssertEqual(jsonTrue.bool!, true) XCTAssertEqual(jsonTrue.boolValue, true) - var jsonFalse:JSON = false + var jsonFalse: JSON = false XCTAssertEqual(jsonFalse.bool!, false) XCTAssertEqual(jsonFalse.boolValue, false) } func testString() { - var json:JSON = "abcd efg, HIJK;LMn" + var json: JSON = "abcd efg, HIJK;LMn" XCTAssertEqual(json.string!, "abcd efg, HIJK;LMn") XCTAssertEqual(json.stringValue, "abcd efg, HIJK;LMn") } - + func testNil() { - let jsonNil_1:JSON = JSON.null + let jsonNil_1: JSON = JSON.null XCTAssert(jsonNil_1 == JSON.null) - let jsonNil_2:JSON = JSON(NSNull.self) + let jsonNil_2: JSON = JSON(NSNull.self) XCTAssert(jsonNil_2 != JSON.null) - let jsonNil_3:JSON = JSON([1:2]) + let jsonNil_3: JSON = JSON([1: 2]) XCTAssert(jsonNil_3 != JSON.null) } - + func testArray() { - let json:JSON = [1,2,"4",5,"6"] - XCTAssertEqual(json.array!, [1,2,"4",5,"6"]) - XCTAssertEqual(json.arrayValue, [1,2,"4",5,"6"]) + let json: JSON = [1, 2, "4", 5, "6"] + XCTAssertEqual(json.array!, [1, 2, "4", 5, "6"]) + XCTAssertEqual(json.arrayValue, [1, 2, "4", 5, "6"]) } - + func testDictionary() { - let json:JSON = ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]] - XCTAssertEqual(json.dictionary!, ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]]) - XCTAssertEqual(json.dictionaryValue, ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]]) + let json: JSON = ["1": 2, "2": 2, "three": 3, "list": ["aa", "bb", "dd"]] + XCTAssertEqual(json.dictionary!, ["1": 2, "2": 2, "three": 3, "list": ["aa", "bb", "dd"]]) + XCTAssertEqual(json.dictionaryValue, ["1": 2, "2": 2, "three": 3, "list": ["aa", "bb", "dd"]]) } } diff --git a/Tests/SwiftyJSONTests/MergeTests.swift b/Tests/SwiftJSONTests/MergeTests.swift similarity index 83% rename from Tests/SwiftyJSONTests/MergeTests.swift rename to Tests/SwiftJSONTests/MergeTests.swift index ddc4a24f..922c459b 100644 --- a/Tests/SwiftyJSONTests/MergeTests.swift +++ b/Tests/SwiftJSONTests/MergeTests.swift @@ -1,5 +1,4 @@ -// -// JSONTests.swift +// MergeTests.swift // // Created by Daniel Kiedrowski on 17.11.16. // @@ -24,78 +23,75 @@ import XCTest import SwiftyJSON -class JSONTests: XCTestCase { - +class MergeTests: XCTestCase { + func testDifferingTypes() { let A = JSON("a") let B = JSON(1) - + do { _ = try A.merged(with: B) - XCTFail() - } catch (let error) { - let error = error as NSError - XCTAssertEqual(error.code, ErrorWrongType) - XCTAssertEqual(error.domain, ErrorDomain) - XCTAssertEqual(error.userInfo[NSLocalizedDescriptionKey] as! String, - "Couldn't merge, because the JSONs differ in type on top level.") - } + } catch let error as SwiftyJSONError { + XCTAssertEqual(error.errorCode, SwiftyJSONError.wrongType.rawValue) + XCTAssertEqual(type(of: error).errorDomain, SwiftyJSONError.errorDomain) + XCTAssertEqual(error.errorUserInfo as! [String: String], [NSLocalizedDescriptionKey: "Couldn't merge, because the JSONs differ in type on top level."]) + } catch _ {} } - + func testPrimitiveType() { let A = JSON("a") let B = JSON("b") XCTAssertEqual(try! A.merged(with: B), B) } - + func testMergeEqual() { let json = JSON(["a": "A"]) XCTAssertEqual(try! json.merged(with: json), json) } - + func testMergeUnequalValues() { let A = JSON(["a": "A"]) let B = JSON(["a": "B"]) XCTAssertEqual(try! A.merged(with: B), B) } - + func testMergeUnequalKeysAndValues() { let A = JSON(["a": "A"]) let B = JSON(["b": "B"]) XCTAssertEqual(try! A.merged(with: B), JSON(["a": "A", "b": "B"])) } - + func testMergeFilledAndEmpty() { let A = JSON(["a": "A"]) let B = JSON([:]) XCTAssertEqual(try! A.merged(with: B), A) } - + func testMergeEmptyAndFilled() { let A = JSON([:]) let B = JSON(["a": "A"]) XCTAssertEqual(try! A.merged(with: B), B) } - + func testMergeArray() { let A = JSON(["a"]) let B = JSON(["b"]) XCTAssertEqual(try! A.merged(with: B), JSON(["a", "b"])) } - + func testMergeNestedJSONs() { let A = JSON([ "nested": [ "A": "a" ] ]) - + let B = JSON([ "nested": [ "A": "b" ] ]) - + XCTAssertEqual(try! A.merged(with: B), B) } } diff --git a/Tests/SwiftJSONTests/MutabilityTests.swift b/Tests/SwiftJSONTests/MutabilityTests.swift new file mode 100644 index 00000000..cc1a5b2d --- /dev/null +++ b/Tests/SwiftJSONTests/MutabilityTests.swift @@ -0,0 +1,148 @@ +// MutabilityTests.swift +// +// Copyright (c) 2014 - 2017 Zigii Wong +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import XCTest +import SwiftyJSON + +class MutabilityTests: XCTestCase { + + func testDictionaryMutability() { + let dictionary: [String: Any] = [ + "string": "STRING", + "number": 9823.212, + "bool": true, + "empty": ["nothing"], + "foo": ["bar": ["1"]], + "bar": ["foo": ["1": "a"]] + ] + + var json = JSON(dictionary) + XCTAssertEqual(json["string"], "STRING") + XCTAssertEqual(json["number"], 9823.212) + XCTAssertEqual(json["bool"], true) + XCTAssertEqual(json["empty"], ["nothing"]) + + json["string"] = "muted" + XCTAssertEqual(json["string"], "muted") + + json["number"] = 9999.0 + XCTAssertEqual(json["number"], 9999.0) + + json["bool"] = false + XCTAssertEqual(json["bool"], false) + + json["empty"] = [] + XCTAssertEqual(json["empty"], []) + + json["new"] = JSON(["foo": "bar"]) + XCTAssertEqual(json["new"], ["foo": "bar"]) + + json["foo"]["bar"] = JSON([]) + XCTAssertEqual(json["foo"]["bar"], []) + + json["bar"]["foo"] = JSON(["2": "b"]) + XCTAssertEqual(json["bar"]["foo"], ["2": "b"]) + } + + func testArrayMutability() { + let array: [Any] = ["1", "2", 3, true, []] + + var json = JSON(array) + XCTAssertEqual(json[0], "1") + XCTAssertEqual(json[1], "2") + XCTAssertEqual(json[2], 3) + XCTAssertEqual(json[3], true) + XCTAssertEqual(json[4], []) + + json[0] = false + XCTAssertEqual(json[0], false) + + json[1] = 2 + XCTAssertEqual(json[1], 2) + + json[2] = "3" + XCTAssertEqual(json[2], "3") + + json[3] = [:] + XCTAssertEqual(json[3], [:]) + + json[4] = [1, 2] + XCTAssertEqual(json[4], [1, 2]) + } + + func testValueMutability() { + var intArray = JSON([0, 1, 2]) + intArray[0] = JSON(55) + XCTAssertEqual(intArray[0], 55) + XCTAssertEqual(intArray[0].intValue, 55) + + var dictionary = JSON(["foo": "bar"]) + dictionary["foo"] = JSON("foo") + XCTAssertEqual(dictionary["foo"], "foo") + XCTAssertEqual(dictionary["foo"].stringValue, "foo") + + var number = JSON(1) + number = JSON("111") + XCTAssertEqual(number, "111") + XCTAssertEqual(number.intValue, 111) + XCTAssertEqual(number.stringValue, "111") + + var boolean = JSON(true) + boolean = JSON(false) + XCTAssertEqual(boolean, false) + XCTAssertEqual(boolean.boolValue, false) + } + + func testArrayRemovability() { + let array = ["Test", "Test2", "Test3"] + var json = JSON(array) + + json.arrayObject?.removeFirst() + XCTAssertEqual(false, json.arrayValue.isEmpty) + XCTAssertEqual(json.arrayValue, ["Test2", "Test3"]) + + json.arrayObject?.removeLast() + XCTAssertEqual(false, json.arrayValue.isEmpty) + XCTAssertEqual(json.arrayValue, ["Test2"]) + + json.arrayObject?.removeAll() + XCTAssertEqual(true, json.arrayValue.isEmpty) + XCTAssertEqual(JSON([]), json) + } + + func testDictionaryRemovability() { + let dictionary: [String: Any] = ["key1": "Value1", "key2": 2, "key3": true] + var json = JSON(dictionary) + + json.dictionaryObject?.removeValue(forKey: "key1") + XCTAssertEqual(false, json.dictionaryValue.isEmpty) + XCTAssertEqual(json.dictionaryValue, ["key2": 2, "key3": true]) + + json.dictionaryObject?.removeValue(forKey: "key3") + XCTAssertEqual(false, json.dictionaryValue.isEmpty) + XCTAssertEqual(json.dictionaryValue, ["key2": 2]) + + json.dictionaryObject?.removeAll() + XCTAssertEqual(true, json.dictionaryValue.isEmpty) + XCTAssertEqual(json.dictionaryValue, [:]) + } +} diff --git a/Tests/SwiftJSONTests/NestedJSONTests.swift b/Tests/SwiftJSONTests/NestedJSONTests.swift new file mode 100644 index 00000000..167c6691 --- /dev/null +++ b/Tests/SwiftJSONTests/NestedJSONTests.swift @@ -0,0 +1,88 @@ +// NestedJSONTests.swift +// +// Created by Hector Matos on 9/27/16. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import XCTest +import SwiftyJSON + +class NestedJSONTests: XCTestCase { + let family: JSON = [ + "names": [ + "Brooke Abigail Matos", + "Rowan Danger Matos" + ], + "motto": "Hey, I don't know about you, but I'm feeling twenty-two! So, release the KrakenDev!" + ] + + func testTopLevelNestedJSON() { + let nestedJSON: JSON = [ + "family": family + ] + XCTAssertNotNil(try? nestedJSON.rawData()) + } + + func testDeeplyNestedJSON() { + let nestedFamily: JSON = [ + "count": 1, + "families": [ + [ + "isACoolFamily": true, + "family": [ + "hello": family + ] + ] + ] + ] + XCTAssertNotNil(try? nestedFamily.rawData()) + } + + func testArrayJSON() { + let arr: [JSON] = ["a", 1, ["b", 2]] + let json = JSON(arr) + XCTAssertEqual(json[0].string, "a") + XCTAssertEqual(json[2, 1].int, 2) + } + + func testDictionaryJSON() { + let json: JSON = ["a": JSON("1"), "b": JSON([1, 2, "3"]), "c": JSON(["aa": "11", "bb": 22])] + XCTAssertEqual(json["a"].string, "1") + XCTAssertEqual(json["b"].array!, [1, 2, "3"]) + XCTAssertEqual(json["c"]["aa"].string, "11") + } + + func testNestedJSON() { + let inner = JSON([ + "some_field": "1" + "2" + ]) + let json = JSON([ + "outer_field": "1" + "2", + "inner_json": inner + ]) + XCTAssertEqual(json["inner_json"], ["some_field": "12"]) + + let foo = "foo" + let json2 = JSON([ + "outer_field": foo, + "inner_json": inner + ]) + XCTAssertEqual(json2["inner_json"].rawValue as! [String: String], ["some_field": "12"]) + } +} diff --git a/Tests/SwiftyJSONTests/NumberTests.swift b/Tests/SwiftJSONTests/NumberTests.swift similarity index 96% rename from Tests/SwiftyJSONTests/NumberTests.swift rename to Tests/SwiftJSONTests/NumberTests.swift index 0ae66b54..9f919ca3 100644 --- a/Tests/SwiftyJSONTests/NumberTests.swift +++ b/Tests/SwiftJSONTests/NumberTests.swift @@ -31,68 +31,68 @@ class NumberTests: XCTestCase { XCTAssertEqual(json.number!, 9876543210.123456789) XCTAssertEqual(json.numberValue, 9876543210.123456789) XCTAssertEqual(json.stringValue, "9876543210.123457") - + json.string = "1000000000000000000000000000.1" XCTAssertNil(json.number) XCTAssertEqual(json.numberValue.description, "1000000000000000000000000000.1") json.string = "1e+27" XCTAssertEqual(json.numberValue.description, "1000000000000000000000000000") - + //setter json.number = NSNumber(value: 123456789.0987654321) XCTAssertEqual(json.number!, 123456789.0987654321) XCTAssertEqual(json.numberValue, 123456789.0987654321) - + json.number = nil XCTAssertEqual(json.numberValue, 0) XCTAssertEqual(json.object as? NSNull, NSNull()) XCTAssertTrue(json.number == nil) - + json.numberValue = 2.9876 XCTAssertEqual(json.number!, 2.9876) } - + func testBool() { var json = JSON(true) XCTAssertEqual(json.bool!, true) XCTAssertEqual(json.boolValue, true) XCTAssertEqual(json.numberValue, true as NSNumber) XCTAssertEqual(json.stringValue, "true") - + json.bool = false XCTAssertEqual(json.bool!, false) XCTAssertEqual(json.boolValue, false) XCTAssertEqual(json.numberValue, false as NSNumber) - + json.bool = nil XCTAssertTrue(json.bool == nil) XCTAssertEqual(json.boolValue, false) XCTAssertEqual(json.numberValue, 0) - + json.boolValue = true XCTAssertEqual(json.bool!, true) XCTAssertEqual(json.boolValue, true) XCTAssertEqual(json.numberValue, true as NSNumber) } - + func testDouble() { var json = JSON(9876543210.123456789) XCTAssertEqual(json.double!, 9876543210.123456789) XCTAssertEqual(json.doubleValue, 9876543210.123456789) XCTAssertEqual(json.numberValue, 9876543210.123456789) XCTAssertEqual(json.stringValue, "9876543210.123457") - + json.double = 2.8765432 XCTAssertEqual(json.double!, 2.8765432) XCTAssertEqual(json.doubleValue, 2.8765432) XCTAssertEqual(json.numberValue, 2.8765432) - + json.doubleValue = 89.0987654 XCTAssertEqual(json.double!, 89.0987654) XCTAssertEqual(json.doubleValue, 89.0987654) XCTAssertEqual(json.numberValue, 89.0987654) - + json.double = nil XCTAssertEqual(json.boolValue, false) XCTAssertEqual(json.doubleValue, 0.0) @@ -103,71 +103,70 @@ class NumberTests: XCTestCase { var json = JSON(54321.12345) XCTAssertTrue(json.float! == 54321.12345) XCTAssertTrue(json.floatValue == 54321.12345) - print(json.numberValue.doubleValue) XCTAssertEqual(json.numberValue, 54321.12345) XCTAssertEqual(json.stringValue, "54321.12345") - + json.double = 23231.65 XCTAssertTrue(json.float! == 23231.65) XCTAssertTrue(json.floatValue == 23231.65) - XCTAssertEqual(json.numberValue, NSNumber(value:23231.65)) - + XCTAssertEqual(json.numberValue, NSNumber(value: 23231.65)) + json.double = -98766.23 XCTAssertEqual(json.float!, -98766.23) XCTAssertEqual(json.floatValue, -98766.23) - XCTAssertEqual(json.numberValue, NSNumber(value:-98766.23)) + XCTAssertEqual(json.numberValue, NSNumber(value: -98766.23)) } - + func testInt() { var json = JSON(123456789) XCTAssertEqual(json.int!, 123456789) XCTAssertEqual(json.intValue, 123456789) XCTAssertEqual(json.numberValue, NSNumber(value: 123456789)) XCTAssertEqual(json.stringValue, "123456789") - + json.int = nil XCTAssertTrue(json.boolValue == false) XCTAssertTrue(json.intValue == 0) XCTAssertEqual(json.numberValue, 0) XCTAssertEqual(json.object as? NSNull, NSNull()) XCTAssertTrue(json.int == nil) - + json.intValue = 76543 XCTAssertEqual(json.int!, 76543) XCTAssertEqual(json.intValue, 76543) XCTAssertEqual(json.numberValue, NSNumber(value: 76543)) - + json.intValue = 98765421 XCTAssertEqual(json.int!, 98765421) XCTAssertEqual(json.intValue, 98765421) XCTAssertEqual(json.numberValue, NSNumber(value: 98765421)) } - + func testUInt() { var json = JSON(123456789) XCTAssertTrue(json.uInt! == 123456789) XCTAssertTrue(json.uIntValue == 123456789) XCTAssertEqual(json.numberValue, NSNumber(value: 123456789)) XCTAssertEqual(json.stringValue, "123456789") - + json.uInt = nil XCTAssertTrue(json.boolValue == false) XCTAssertTrue(json.uIntValue == 0) XCTAssertEqual(json.numberValue, 0) XCTAssertEqual(json.object as? NSNull, NSNull()) XCTAssertTrue(json.uInt == nil) - + json.uIntValue = 76543 XCTAssertTrue(json.uInt! == 76543) XCTAssertTrue(json.uIntValue == 76543) XCTAssertEqual(json.numberValue, NSNumber(value: 76543)) - + json.uIntValue = 98765421 XCTAssertTrue(json.uInt! == 98765421) XCTAssertTrue(json.uIntValue == 98765421) XCTAssertEqual(json.numberValue, NSNumber(value: 98765421)) } - + func testInt8() { let n127 = NSNumber(value: 127) var json = JSON(n127) @@ -176,7 +175,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n127) XCTAssertEqual(json.numberValue, n127) XCTAssertEqual(json.stringValue, "127") - + let nm128 = NSNumber(value: -128) json.int8Value = nm128.int8Value XCTAssertTrue(json.int8! == nm128.int8Value) @@ -184,7 +183,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == nm128) XCTAssertEqual(json.numberValue, nm128) XCTAssertEqual(json.stringValue, "-128") - + let n0 = NSNumber(value: 0 as Int8) json.int8Value = n0.int8Value XCTAssertTrue(json.int8! == n0.int8Value) @@ -192,8 +191,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n0) XCTAssertEqual(json.numberValue, n0) XCTAssertEqual(json.stringValue, "0") - - + let n1 = NSNumber(value: 1 as Int8) json.int8Value = n1.int8Value XCTAssertTrue(json.int8! == n1.int8Value) @@ -202,7 +200,7 @@ class NumberTests: XCTestCase { XCTAssertEqual(json.numberValue, n1) XCTAssertEqual(json.stringValue, "1") } - + func testUInt8() { let n255 = NSNumber(value: 255) var json = JSON(n255) @@ -211,7 +209,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n255) XCTAssertEqual(json.numberValue, n255) XCTAssertEqual(json.stringValue, "255") - + let nm2 = NSNumber(value: 2) json.uInt8Value = nm2.uint8Value XCTAssertTrue(json.uInt8! == nm2.uint8Value) @@ -219,7 +217,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == nm2) XCTAssertEqual(json.numberValue, nm2) XCTAssertEqual(json.stringValue, "2") - + let nm0 = NSNumber(value: 0) json.uInt8Value = nm0.uint8Value XCTAssertTrue(json.uInt8! == nm0.uint8Value) @@ -238,7 +236,7 @@ class NumberTests: XCTestCase { } func testInt16() { - + let n32767 = NSNumber(value: 32767) var json = JSON(n32767) XCTAssertTrue(json.int16! == n32767.int16Value) @@ -246,7 +244,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n32767) XCTAssertEqual(json.numberValue, n32767) XCTAssertEqual(json.stringValue, "32767") - + let nm32768 = NSNumber(value: -32768) json.int16Value = nm32768.int16Value XCTAssertTrue(json.int16! == nm32768.int16Value) @@ -254,7 +252,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == nm32768) XCTAssertEqual(json.numberValue, nm32768) XCTAssertEqual(json.stringValue, "-32768") - + let n0 = NSNumber(value: 0) json.int16Value = n0.int16Value XCTAssertTrue(json.int16! == n0.int16Value) @@ -262,7 +260,7 @@ class NumberTests: XCTestCase { XCTAssertEqual(json.number, n0) XCTAssertEqual(json.numberValue, n0) XCTAssertEqual(json.stringValue, "0") - + let n1 = NSNumber(value: 1) json.int16 = n1.int16Value XCTAssertTrue(json.int16! == n1.int16Value) @@ -299,7 +297,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n2147483647) XCTAssertEqual(json.numberValue, n2147483647) XCTAssertEqual(json.stringValue, "2147483647") - + let n32767 = NSNumber(value: 32767) json.int32 = n32767.int32Value XCTAssertTrue(json.int32! == n32767.int32Value) @@ -307,7 +305,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n32767) XCTAssertEqual(json.numberValue, n32767) XCTAssertEqual(json.stringValue, "32767") - + let nm2147483648 = NSNumber(value: -2147483648) json.int32Value = nm2147483648.int32Value XCTAssertTrue(json.int32! == nm2147483648.int32Value) @@ -316,7 +314,7 @@ class NumberTests: XCTestCase { XCTAssertEqual(json.numberValue, nm2147483648) XCTAssertEqual(json.stringValue, "-2147483648") } - + func testUInt32() { let n2147483648 = NSNumber(value: 2147483648 as UInt32) var json = JSON(n2147483648) @@ -325,7 +323,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n2147483648) XCTAssertEqual(json.numberValue, n2147483648) XCTAssertEqual(json.stringValue, "2147483648") - + let n32767 = NSNumber(value: 32767 as UInt32) json.uInt32 = n32767.uint32Value XCTAssertTrue(json.uInt32! == n32767.uint32Value) @@ -333,7 +331,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n32767) XCTAssertEqual(json.numberValue, n32767) XCTAssertEqual(json.stringValue, "32767") - + let n0 = NSNumber(value: 0 as UInt32) json.uInt32Value = n0.uint32Value XCTAssertTrue(json.uInt32! == n0.uint32Value) @@ -351,7 +349,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == int64Max) XCTAssertEqual(json.numberValue, int64Max) XCTAssertEqual(json.stringValue, int64Max.stringValue) - + let n32767 = NSNumber(value: 32767) json.int64 = n32767.int64Value XCTAssertTrue(json.int64! == n32767.int64Value) @@ -359,7 +357,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == n32767) XCTAssertEqual(json.numberValue, n32767) XCTAssertEqual(json.stringValue, "32767") - + let int64Min = NSNumber(value: (INT64_MAX-1) * -1) json.int64Value = int64Min.int64Value XCTAssertTrue(json.int64! == int64Min.int64Value) @@ -368,7 +366,7 @@ class NumberTests: XCTestCase { XCTAssertEqual(json.numberValue, int64Min) XCTAssertEqual(json.stringValue, int64Min.stringValue) } - + func testUInt64() { let uInt64Max = NSNumber(value: UINT64_MAX) var json = JSON(uInt64Max) @@ -377,7 +375,7 @@ class NumberTests: XCTestCase { XCTAssertTrue(json.number! == uInt64Max) XCTAssertEqual(json.numberValue, uInt64Max) XCTAssertEqual(json.stringValue, uInt64Max.stringValue) - + let n32767 = NSNumber(value: 32767) json.int64 = n32767.int64Value XCTAssertTrue(json.int64! == n32767.int64Value) diff --git a/Tests/SwiftyJSONTests/PerformanceTests.swift b/Tests/SwiftJSONTests/PerformanceTests.swift similarity index 68% rename from Tests/SwiftyJSONTests/PerformanceTests.swift rename to Tests/SwiftJSONTests/PerformanceTests.swift index e3ed9760..c0e6cc0b 100644 --- a/Tests/SwiftyJSONTests/PerformanceTests.swift +++ b/Tests/SwiftJSONTests/PerformanceTests.swift @@ -26,46 +26,60 @@ import SwiftyJSON class PerformanceTests: XCTestCase { var testData: Data! - + override func setUp() { super.setUp() - - if let file = Bundle(for:PerformanceTests.self).path(forResource: "Tests", ofType: "json") { - self.testData = try? Data(contentsOf: URL(fileURLWithPath: file)) + + #if SWIFT_PACKAGE + let testBundle = Bundle.module + #else + let testBundle = Bundle(for: PerformanceTests.self) + #endif + if let file = testBundle.url(forResource: "Tests", withExtension: "json") { + self.testData = try? Data(contentsOf: file) } else { XCTFail("Can't find the test JSON file") } } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testInitPerformance() { - self.measure() { + self.measure { for _ in 1...100 { - let json = JSON(data:self.testData) + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } XCTAssertTrue(json != JSON.null) } } } - + func testObjectMethodPerformance() { - let json = JSON(data:self.testData) - self.measure() { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + self.measure { for _ in 1...100 { - let object:Any? = json.object + let object: Any? = json.object XCTAssertTrue(object != nil) } } } func testArrayMethodPerformance() { - let json = JSON(data:self.testData) - self.measure() { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + self.measure { for _ in 1...100 { - autoreleasepool{ + autoreleasepool { if let array = json.array { XCTAssertTrue(array.count > 0) } @@ -73,12 +87,15 @@ class PerformanceTests: XCTestCase { } } } - + func testDictionaryMethodPerformance() { - let json = JSON(data:testData)[0] - self.measure() { + guard let json = try? JSON(data: self.testData)[0] else { + XCTFail("Unable to parse testData") + return + } + self.measure { for _ in 1...100 { - autoreleasepool{ + autoreleasepool { if let dictionary = json.dictionary { XCTAssertTrue(dictionary.count > 0) } @@ -86,12 +103,15 @@ class PerformanceTests: XCTestCase { } } } - + func testRawStringMethodPerformance() { - let json = JSON(data:testData) - self.measure() { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + self.measure { for _ in 1...100 { - autoreleasepool{ + autoreleasepool { let string = json.rawString() XCTAssertTrue(string != nil) } @@ -108,11 +128,11 @@ class PerformanceTests: XCTestCase { ]) } let json = JSON(data) - - self.measure() { - autoreleasepool{ + + self.measure { + autoreleasepool { if let dictionary = json.dictionary { - XCTAssertTrue(dictionary.count > 0) + XCTAssertTrue(dictionary.count == 100001) } else { XCTFail("dictionary should not be nil") } diff --git a/Tests/SwiftyJSONTests/PrintableTests.swift b/Tests/SwiftJSONTests/PrintableTests.swift similarity index 91% rename from Tests/SwiftyJSONTests/PrintableTests.swift rename to Tests/SwiftJSONTests/PrintableTests.swift index f60fc8c1..ba5863d1 100644 --- a/Tests/SwiftyJSONTests/PrintableTests.swift +++ b/Tests/SwiftJSONTests/PrintableTests.swift @@ -25,37 +25,37 @@ import SwiftyJSON class PrintableTests: XCTestCase { func testNumber() { - let json:JSON = 1234567890.876623 + let json: JSON = 1234567890.876623 XCTAssertEqual(json.description, "1234567890.876623") XCTAssertEqual(json.debugDescription, "1234567890.876623") } - + func testBool() { - let jsonTrue:JSON = true + let jsonTrue: JSON = true XCTAssertEqual(jsonTrue.description, "true") XCTAssertEqual(jsonTrue.debugDescription, "true") - let jsonFalse:JSON = false + let jsonFalse: JSON = false XCTAssertEqual(jsonFalse.description, "false") XCTAssertEqual(jsonFalse.debugDescription, "false") } - + func testString() { - let json:JSON = "abcd efg, HIJK;LMn" + let json: JSON = "abcd efg, HIJK;LMn" XCTAssertEqual(json.description, "abcd efg, HIJK;LMn") XCTAssertEqual(json.debugDescription, "abcd efg, HIJK;LMn") } - + func testNil() { - let jsonNil_1:JSON = JSON.null + let jsonNil_1: JSON = JSON.null XCTAssertEqual(jsonNil_1.description, "null") XCTAssertEqual(jsonNil_1.debugDescription, "null") - let jsonNil_2:JSON = JSON(NSNull()) + let jsonNil_2: JSON = JSON(NSNull()) XCTAssertEqual(jsonNil_2.description, "null") XCTAssertEqual(jsonNil_2.debugDescription, "null") } - + func testArray() { - let json:JSON = [1,2,"4",5,"6"] + let json: JSON = [1, 2, "4", 5, "6"] var description = json.description.replacingOccurrences(of: "\n", with: "") description = description.replacingOccurrences(of: " ", with: "") XCTAssertEqual(description, "[1,2,\"4\",5,\"6\"]") @@ -74,7 +74,7 @@ class PrintableTests: XCTestCase { } func testArrayWithOptionals() { - let array = [1,2,"4",5,"6",nil] as [Any?] + let array = [1, 2, "4", 5, "6", nil] as [Any?] let json = JSON(array) guard var description = json.rawString([.castNilToNSNull: true]) else { XCTFail("could not represent array") @@ -86,9 +86,9 @@ class PrintableTests: XCTestCase { XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) XCTAssertTrue(json.debugDescription.lengthOfBytes(using: String.Encoding.utf8) > 0) } - + func testDictionary() { - let json:JSON = ["1":2,"2":"two", "3":3] + let json: JSON = ["1": 2, "2": "two", "3": 3] var debugDescription = json.debugDescription.replacingOccurrences(of: "\n", with: "") debugDescription = debugDescription.replacingOccurrences(of: " ", with: "") XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) @@ -98,7 +98,7 @@ class PrintableTests: XCTestCase { } func testDictionaryWithStrings() { - let dict = ["foo":"{\"bar\":123}"] as [String : Any] + let dict = ["foo": "{\"bar\":123}"] as [String: Any] let json = JSON(dict) var debugDescription = json.debugDescription.replacingOccurrences(of: "\n", with: "") debugDescription = debugDescription.replacingOccurrences(of: " ", with: "") @@ -108,7 +108,7 @@ class PrintableTests: XCTestCase { } func testDictionaryWithOptionals() { - let dict = ["1":2, "2":"two", "3": nil] as [String: Any?] + let dict = ["1": 2, "2": "two", "3": nil] as [String: Any?] let json = JSON(dict) guard var description = json.rawString([.castNilToNSNull: true]) else { XCTFail("could not represent dictionary") diff --git a/Tests/SwiftyJSONTests/RawRepresentableTests.swift b/Tests/SwiftJSONTests/RawRepresentableTests.swift similarity index 75% rename from Tests/SwiftyJSONTests/RawRepresentableTests.swift rename to Tests/SwiftJSONTests/RawRepresentableTests.swift index 9ebf9b2e..88a70de8 100644 --- a/Tests/SwiftyJSONTests/RawRepresentableTests.swift +++ b/Tests/SwiftJSONTests/RawRepresentableTests.swift @@ -26,40 +26,44 @@ import SwiftyJSON class RawRepresentableTests: XCTestCase { func testNumber() { - var json:JSON = JSON(rawValue: 948394394.347384 as NSNumber)! + var json: JSON = JSON(rawValue: 948394394.347384 as NSNumber)! XCTAssertEqual(json.int!, 948394394) XCTAssertEqual(json.intValue, 948394394) XCTAssertEqual(json.double!, 948394394.347384) XCTAssertEqual(json.doubleValue, 948394394.347384) - XCTAssertTrue(json.float! == 948394394.347384) - XCTAssertTrue(json.floatValue == 948394394.347384) - + XCTAssertEqual(json.float!, 948394394.347384) + XCTAssertEqual(json.floatValue, 948394394.347384) + let object: Any = json.rawValue - XCTAssertEqual(object as? Int, 948394394) + if let int = object as? Int { + XCTAssertEqual(int, 948394394) + } XCTAssertEqual(object as? Double, 948394394.347384) - XCTAssertTrue(object as! Float == 948394394.347384) + if let float = object as? Float { + XCTAssertEqual(float, 948394394.347384) + } XCTAssertEqual(object as? NSNumber, 948394394.347384) } - + func testBool() { - var jsonTrue:JSON = JSON(rawValue: true as NSNumber)! + var jsonTrue: JSON = JSON(rawValue: true as NSNumber)! XCTAssertEqual(jsonTrue.bool!, true) XCTAssertEqual(jsonTrue.boolValue, true) - - var jsonFalse:JSON = JSON(rawValue: false)! + + var jsonFalse: JSON = JSON(rawValue: false)! XCTAssertEqual(jsonFalse.bool!, false) XCTAssertEqual(jsonFalse.boolValue, false) - + let objectTrue = jsonTrue.rawValue XCTAssertEqual(objectTrue as? Bool, true) - + let objectFalse = jsonFalse.rawValue XCTAssertEqual(objectFalse as? Bool, false) } - + func testString() { let string = "The better way to deal with JSON data in Swift." - if let json:JSON = JSON(rawValue: string) { + if let json: JSON = JSON(rawValue: string) { XCTAssertEqual(json.string!, string) XCTAssertEqual(json.stringValue, string) XCTAssertTrue(json.array == nil) @@ -71,30 +75,36 @@ class RawRepresentableTests: XCTestCase { } else { XCTFail("Should not run into here") } - + let object: Any = JSON(rawValue: string)!.rawValue XCTAssertEqual(object as? String, string) } - + func testNil() { - if let _ = JSON(rawValue: NSObject()) { + if JSON(rawValue: NSObject()) != nil { XCTFail("Should not run into here") } + + do { + let n: Int? = nil + let json = JSON(n as Any) + XCTAssertEqual(json.type, .null) + } } - + func testArray() { - let array = [1,2,"3",4102,"5632", "abocde", "!@# $%^&*()"] as NSArray - if let json:JSON = JSON(rawValue: array) { + let array = [1, 2, "3", 4102, "5632", "abocde", "!@# $%^&*()"] as NSArray + if let json: JSON = JSON(rawValue: array) { XCTAssertEqual(json, JSON(array)) } - + let object: Any = JSON(rawValue: array)!.rawValue XCTAssertTrue(array == object as! NSArray) } - + func testDictionary() { - let dictionary = ["1":2,"2":2,"three":3,"list":["aa","bb","dd"]] as NSDictionary - if let json:JSON = JSON(rawValue: dictionary) { + let dictionary = ["1": 2, "2": 2, "three": 3, "list": ["aa", "bb", "dd"]] as NSDictionary + if let json: JSON = JSON(rawValue: dictionary) { XCTAssertEqual(json, JSON(dictionary)) } diff --git a/Tests/SwiftyJSONTests/RawTests.swift b/Tests/SwiftJSONTests/RawTests.swift similarity index 74% rename from Tests/SwiftyJSONTests/RawTests.swift rename to Tests/SwiftJSONTests/RawTests.swift index 7693d8e3..036060fb 100644 --- a/Tests/SwiftyJSONTests/RawTests.swift +++ b/Tests/SwiftJSONTests/RawTests.swift @@ -26,27 +26,25 @@ import SwiftyJSON class RawTests: XCTestCase { func testRawData() { - let json: JSON = ["somekey" : "some string value"] + let json: JSON = ["somekey": "some string value"] let expectedRawData = "{\"somekey\":\"some string value\"}".data(using: String.Encoding.utf8) do { let data: Data = try json.rawData() XCTAssertEqual(expectedRawData, data) - } catch _ { - XCTFail() - } + } catch _ {} } - + func testInvalidJSONForRawData() { let json: JSON = "...xyz" do { _ = try json.rawData() - } catch let error as NSError { - XCTAssertEqual(error.code, ErrorInvalidJSON) - } + } catch let error as SwiftyJSONError { + XCTAssertEqual(error, SwiftyJSONError.invalidJSON) + } catch _ {} } - + func testArray() { - let json:JSON = [1, "2", 3.12, NSNull(), true, ["name": "Jack"]] + let json: JSON = [1, "2", 3.12, NSNull(), true, ["name": "Jack"]] let data: Data? do { data = try json.rawData() @@ -56,11 +54,10 @@ class RawTests: XCTestCase { let string = json.rawString() XCTAssertTrue (data != nil) XCTAssertTrue (string!.lengthOfBytes(using: String.Encoding.utf8) > 0) - print(string!) } - + func testDictionary() { - let json:JSON = ["number":111111.23456789, "name":"Jack", "list":[1,2,3,4], "bool":false, "null":NSNull()] + let json: JSON = ["number": 111111.23456789, "name": "Jack", "list": [1, 2, 3, 4], "bool": false, "null": NSNull()] let data: Data? do { data = try json.rawData() @@ -70,26 +67,39 @@ class RawTests: XCTestCase { let string = json.rawString() XCTAssertTrue (data != nil) XCTAssertTrue (string!.lengthOfBytes(using: String.Encoding.utf8) > 0) - print(string!) } - + func testString() { - let json:JSON = "I'm a json" + let json: JSON = "I'm a json" XCTAssertEqual(json.rawString(), "I'm a json") } - + func testNumber() { - let json:JSON = 123456789.123 + let json: JSON = 123456789.123 XCTAssertEqual(json.rawString(), "123456789.123") } - + func testBool() { - let json:JSON = true + let json: JSON = true XCTAssertEqual(json.rawString(), "true") } - + func testNull() { - let json:JSON = JSON.null + let json: JSON = JSON.null XCTAssertEqual(json.rawString(), "null") } + + func testNestedJSON() { + let inner: JSON = ["name": "john doe"] + let json: JSON = ["level": 1337, "user": inner] + let data: Data? + do { + data = try json.rawData() + } catch _ { + data = nil + } + let string = json.rawString() + XCTAssertNotNil(data) + XCTAssertNotNil(string) + } } diff --git a/Tests/SwiftyJSONTests/SequenceTypeTests.swift b/Tests/SwiftJSONTests/SequenceTypeTests.swift similarity index 75% rename from Tests/SwiftyJSONTests/SequenceTypeTests.swift rename to Tests/SwiftJSONTests/SequenceTypeTests.swift index 8f164c4c..a039453f 100644 --- a/Tests/SwiftyJSONTests/SequenceTypeTests.swift +++ b/Tests/SwiftJSONTests/SequenceTypeTests.swift @@ -1,4 +1,3 @@ -// // SequenceTypeTests.swift // // Copyright (c) 2014 - 2017 Pinglin Tang @@ -26,10 +25,20 @@ import SwiftyJSON class SequenceTypeTests: XCTestCase { + var testData: Data? + func testJSONFile() { - if let file = Bundle(for:BaseTests.self).path(forResource: "Tests", ofType: "json") { - let testData = try? Data(contentsOf: URL(fileURLWithPath: file)) - let json = JSON(data:testData!) + #if SWIFT_PACKAGE + let testBundle = Bundle.module + #else + let testBundle = Bundle(for: SequenceTypeTests.self) + #endif + if let file = testBundle.url(forResource: "Tests", withExtension: "json") { + self.testData = try? Data(contentsOf: file) + guard let json = try? JSON(data: self.testData!) else { + XCTFail("Unable to parse the data") + return + } for (index, sub) in json { switch (index as NSString).integerValue { case 0: @@ -48,7 +57,7 @@ class SequenceTypeTests: XCTestCase { } func testArrayAllNumber() { - var json:JSON = [1,2.0,3.3,123456789,987654321.123456789] + var json: JSON = [1, 2.0, 3.3, 123456789, 987654321.123456789] XCTAssertEqual(json.count, 5) var index = 0 @@ -60,11 +69,11 @@ class SequenceTypeTests: XCTestCase { index += 1 } XCTAssertEqual(index, 5) - XCTAssertEqual(array, [1,2.0,3.3,123456789,987654321.123456789]) + XCTAssertEqual(array, [1, 2.0, 3.3, 123456789, 987654321.123456789]) } func testArrayAllBool() { - var json:JSON = JSON([true, false, false, true, true]) + var json: JSON = JSON([true, false, false, true, true]) XCTAssertEqual(json.count, 5) var index = 0 @@ -80,7 +89,7 @@ class SequenceTypeTests: XCTestCase { } func testArrayAllString() { - var json:JSON = JSON(rawValue: ["aoo","bpp","zoo"] as NSArray)! + var json: JSON = JSON(rawValue: ["aoo", "bpp", "zoo"] as NSArray)! XCTAssertEqual(json.count, 3) var index = 0 @@ -92,11 +101,11 @@ class SequenceTypeTests: XCTestCase { index += 1 } XCTAssertEqual(index, 3) - XCTAssertEqual(array, ["aoo","bpp","zoo"]) + XCTAssertEqual(array, ["aoo", "bpp", "zoo"]) } func testArrayWithNull() { - var json:JSON = JSON(rawValue: ["aoo","bpp", NSNull() ,"zoo"] as NSArray)! + var json: JSON = JSON(rawValue: ["aoo", "bpp", NSNull(), "zoo"] as NSArray)! XCTAssertEqual(json.count, 4) var index = 0 @@ -113,7 +122,7 @@ class SequenceTypeTests: XCTestCase { } func testArrayAllDictionary() { - var json:JSON = [["1":1, "2":2], ["a":"A", "b":"B"], ["null":NSNull()]] + var json: JSON = [["1": 1, "2": 2], ["a": "A", "b": "B"], ["null": NSNull()]] XCTAssertEqual(json.count, 3) var index = 0 @@ -125,19 +134,19 @@ class SequenceTypeTests: XCTestCase { index += 1 } XCTAssertEqual(index, 3) - XCTAssertEqual((array[0] as! [String : Int])["1"]!, 1) - XCTAssertEqual((array[0] as! [String : Int])["2"]!, 2) - XCTAssertEqual((array[1] as! [String : String])["a"]!, "A") - XCTAssertEqual((array[1] as! [String : String])["b"]!, "B") - XCTAssertEqual((array[2] as! [String : NSNull])["null"]!, NSNull()) + XCTAssertEqual((array[0] as! [String: Int])["1"]!, 1) + XCTAssertEqual((array[0] as! [String: Int])["2"]!, 2) + XCTAssertEqual((array[1] as! [String: String])["a"]!, "A") + XCTAssertEqual((array[1] as! [String: String])["b"]!, "B") + XCTAssertEqual((array[2] as! [String: NSNull])["null"]!, NSNull()) } func testDictionaryAllNumber() { - var json:JSON = ["double":1.11111, "int":987654321] + var json: JSON = ["double": 1.11111, "int": 987654321] XCTAssertEqual(json.count, 2) var index = 0 - var dictionary = [String:NSNumber]() + var dictionary = [String: NSNumber]() for (key, sub) in json { XCTAssertEqual(sub, json[key]) dictionary[key] = sub.number! @@ -150,11 +159,11 @@ class SequenceTypeTests: XCTestCase { } func testDictionaryAllBool() { - var json:JSON = ["t":true, "f":false, "false":false, "tr":true, "true":true] + var json: JSON = ["t": true, "f": false, "false": false, "tr": true, "true": true] XCTAssertEqual(json.count, 5) var index = 0 - var dictionary = [String:Bool]() + var dictionary = [String: Bool]() for (key, sub) in json { XCTAssertEqual(sub, json[key]) dictionary[key] = sub.bool! @@ -167,11 +176,11 @@ class SequenceTypeTests: XCTestCase { } func testDictionaryAllString() { - var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","z":"zoo"] as NSDictionary)! + var json: JSON = JSON(rawValue: ["a": "aoo", "bb": "bpp", "z": "zoo"] as NSDictionary)! XCTAssertEqual(json.count, 3) var index = 0 - var dictionary = [String:String]() + var dictionary = [String: String]() for (key, sub) in json { XCTAssertEqual(sub, json[key]) dictionary[key] = sub.string! @@ -184,11 +193,11 @@ class SequenceTypeTests: XCTestCase { } func testDictionaryWithNull() { - var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","null":NSNull(), "z":"zoo"] as NSDictionary)! + var json: JSON = JSON(rawValue: ["a": "aoo", "bb": "bpp", "null": NSNull(), "z": "zoo"] as NSDictionary)! XCTAssertEqual(json.count, 4) var index = 0 - var dictionary = [String:AnyObject]() + var dictionary = [String: AnyObject]() for (key, sub) in json { XCTAssertEqual(sub, json[key]) dictionary[key] = sub.object as AnyObject? @@ -202,12 +211,12 @@ class SequenceTypeTests: XCTestCase { } func testDictionaryAllArray() { - var json:JSON = JSON (["Number":[NSNumber(value:1),NSNumber(value:2.123456),NSNumber(value:123456789)], "String":["aa","bbb","cccc"], "Mix":[true, "766", NSNull(), 655231.9823]]) + var json: JSON = JSON (["Number": [NSNumber(value: 1), NSNumber(value: 2.123456), NSNumber(value: 123456789)], "String": ["aa", "bbb", "cccc"], "Mix": [true, "766", NSNull(), 655231.9823]]) XCTAssertEqual(json.count, 3) var index = 0 - var dictionary = [String:AnyObject]() + var dictionary = [String: AnyObject]() for (key, sub) in json { XCTAssertEqual(sub, json[key]) dictionary[key] = sub.object as AnyObject? diff --git a/Tests/SwiftyJSONTests/StringTests.swift b/Tests/SwiftJSONTests/StringTests.swift similarity index 90% rename from Tests/SwiftyJSONTests/StringTests.swift rename to Tests/SwiftJSONTests/StringTests.swift index 8d8e6ebc..9ce10643 100644 --- a/Tests/SwiftyJSONTests/StringTests.swift +++ b/Tests/SwiftJSONTests/StringTests.swift @@ -35,10 +35,10 @@ class StringTests: XCTestCase { XCTAssertEqual(json.string!, "12345?67890.@#") XCTAssertEqual(json.stringValue, "12345?67890.@#") } - + func testUrl() { let json = JSON("http://github.com") - XCTAssertEqual(json.url!, URL(string:"http://github.com")!) + XCTAssertEqual(json.url!, URL(string: "http://github.com")!) } func testBool() { @@ -56,6 +56,16 @@ class StringTests: XCTestCase { XCTAssertTrue(json.boolValue) } + func testBoolWithYes() { + let json = JSON("Yes") + XCTAssertTrue(json.boolValue) + } + + func testBoolWith1() { + let json = JSON("1") + XCTAssertTrue(json.boolValue) + } + func testUrlPercentEscapes() { let emDash = "\\u2014" let urlString = "http://examble.com/unencoded" + emDash + "string" diff --git a/Tests/SwiftyJSONTests/SubscriptTests.swift b/Tests/SwiftJSONTests/SubscriptTests.swift similarity index 55% rename from Tests/SwiftyJSONTests/SubscriptTests.swift rename to Tests/SwiftJSONTests/SubscriptTests.swift index 2a5cd97e..5b399f40 100644 --- a/Tests/SwiftyJSONTests/SubscriptTests.swift +++ b/Tests/SwiftJSONTests/SubscriptTests.swift @@ -26,63 +26,63 @@ import SwiftyJSON class SubscriptTests: XCTestCase { func testArrayAllNumber() { - var json:JSON = [1,2.0,3.3,123456789,987654321.123456789] - XCTAssertTrue(json == [1,2.0,3.3,123456789,987654321.123456789]) + var json: JSON = [1, 2.0, 3.3, 123456789, 987654321.123456789] + XCTAssertTrue(json == [1, 2.0, 3.3, 123456789, 987654321.123456789]) XCTAssertTrue(json[0] == 1) XCTAssertEqual(json[1].double!, 2.0) XCTAssertTrue(json[2].floatValue == 3.3) XCTAssertEqual(json[3].int!, 123456789) XCTAssertEqual(json[4].doubleValue, 987654321.123456789) - + json[0] = 1.9 json[1] = 2.899 json[2] = 3.567 json[3] = 0.999 json[4] = 98732 - + XCTAssertTrue(json[0] == 1.9) XCTAssertEqual(json[1].doubleValue, 2.899) XCTAssertTrue(json[2] == 3.567) XCTAssertTrue(json[3].float! == 0.999) XCTAssertTrue(json[4].intValue == 98732) } - + func testArrayAllBool() { - var json:JSON = [true, false, false, true, true] + var json: JSON = [true, false, false, true, true] XCTAssertTrue(json == [true, false, false, true, true]) XCTAssertTrue(json[0] == true) XCTAssertTrue(json[1] == false) XCTAssertTrue(json[2] == false) XCTAssertTrue(json[3] == true) XCTAssertTrue(json[4] == true) - + json[0] = false json[4] = true XCTAssertTrue(json[0] == false) XCTAssertTrue(json[4] == true) } - + func testArrayAllString() { - var json:JSON = JSON(rawValue: ["aoo","bpp","zoo"] as NSArray)! - XCTAssertTrue(json == ["aoo","bpp","zoo"]) + var json: JSON = JSON(rawValue: ["aoo", "bpp", "zoo"] as NSArray)! + XCTAssertTrue(json == ["aoo", "bpp", "zoo"]) XCTAssertTrue(json[0] == "aoo") XCTAssertTrue(json[1] == "bpp") XCTAssertTrue(json[2] == "zoo") - + json[1] = "update" XCTAssertTrue(json[0] == "aoo") XCTAssertTrue(json[1] == "update") XCTAssertTrue(json[2] == "zoo") } - + func testArrayWithNull() { - var json:JSON = JSON(rawValue: ["aoo","bpp", NSNull() ,"zoo"] as NSArray)! + var json: JSON = JSON(rawValue: ["aoo", "bpp", NSNull(), "zoo"] as NSArray)! XCTAssertTrue(json[0] == "aoo") XCTAssertTrue(json[1] == "bpp") XCTAssertNil(json[2].string) XCTAssertNotNil(json[2].null) XCTAssertTrue(json[3] == "zoo") - + json[2] = "update" json[3] = JSON(NSNull()) XCTAssertTrue(json[0] == "aoo") @@ -91,27 +91,27 @@ class SubscriptTests: XCTestCase { XCTAssertNil(json[3].string) XCTAssertNotNil(json[3].null) } - + func testArrayAllDictionary() { - var json:JSON = [["1":1, "2":2], ["a":"A", "b":"B"], ["null":NSNull()]] - XCTAssertTrue(json[0] == ["1":1, "2":2]) - XCTAssertEqual(json[1].dictionary!, ["a":"A", "b":"B"]) - XCTAssertEqual(json[2], JSON(["null":NSNull()])) + var json: JSON = [["1": 1, "2": 2], ["a": "A", "b": "B"], ["null": NSNull()]] + XCTAssertTrue(json[0] == ["1": 1, "2": 2]) + XCTAssertEqual(json[1].dictionary!, ["a": "A", "b": "B"]) + XCTAssertEqual(json[2], JSON(["null": NSNull()])) XCTAssertTrue(json[0]["1"] == 1) XCTAssertTrue(json[0]["2"] == 2) XCTAssertEqual(json[1]["a"], JSON(rawValue: "A")!) XCTAssertEqual(json[1]["b"], JSON("B")) XCTAssertNotNil(json[2]["null"].null) - XCTAssertNotNil(json[2,"null"].null) - let keys:[JSONSubscriptType] = [1, "a"] + XCTAssertNotNil(json[2, "null"].null) + let keys: [JSONSubscriptType] = [1, "a"] XCTAssertEqual(json[keys], JSON(rawValue: "A")!) } - + func testDictionaryAllNumber() { - var json:JSON = ["double":1.11111, "int":987654321] + var json: JSON = ["double": 1.11111, "int": 987654321] XCTAssertEqual(json["double"].double!, 1.11111) XCTAssertTrue(json["int"] == 987654321) - + json["double"] = 2.2222 json["int"] = 123456789 json["add"] = 7890 @@ -119,9 +119,11 @@ class SubscriptTests: XCTestCase { XCTAssertEqual(json["int"].doubleValue, 123456789.0) XCTAssertEqual(json["add"].intValue, 7890) } - + func testDictionaryAllBool() { - var json:JSON = ["t":true, "f":false, "false":false, "tr":true, "true":true] + var json: JSON = ["t": true, "f": false, "false": false, "tr": true, "true": true, "yes": true, "1": true] + XCTAssertTrue(json["1"] == true) + XCTAssertTrue(json["yes"] == true) XCTAssertTrue(json["t"] == true) XCTAssertTrue(json["f"] == false) XCTAssertTrue(json["false"] == false) @@ -133,133 +135,133 @@ class SubscriptTests: XCTestCase { XCTAssertTrue(json["f"] == true) XCTAssertTrue(json["tr"] == JSON(false)) } - + func testDictionaryAllString() { - var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","z":"zoo"] as NSDictionary)! + var json: JSON = JSON(rawValue: ["a": "aoo", "bb": "bpp", "z": "zoo"] as NSDictionary)! XCTAssertTrue(json["a"] == "aoo") XCTAssertEqual(json["bb"], JSON("bpp")) XCTAssertTrue(json["z"] == "zoo") - + json["bb"] = "update" XCTAssertTrue(json["a"] == "aoo") XCTAssertTrue(json["bb"] == "update") XCTAssertTrue(json["z"] == "zoo") } - + func testDictionaryWithNull() { - var json:JSON = JSON(rawValue: ["a":"aoo","bb":"bpp","null":NSNull(), "z":"zoo"] as NSDictionary)! + var json: JSON = JSON(rawValue: ["a": "aoo", "bb": "bpp", "null": NSNull(), "z": "zoo"] as NSDictionary)! XCTAssertTrue(json["a"] == "aoo") XCTAssertEqual(json["bb"], JSON("bpp")) XCTAssertEqual(json["null"], JSON(NSNull())) XCTAssertTrue(json["z"] == "zoo") - + json["null"] = "update" XCTAssertTrue(json["a"] == "aoo") XCTAssertTrue(json["null"] == "update") XCTAssertTrue(json["z"] == "zoo") } - + func testDictionaryAllArray() { //Swift bug: [1, 2.01,3.09] is convert to [1, 2, 3] (Array) - let json:JSON = JSON ([[NSNumber(value:1),NSNumber(value:2.123456),NSNumber(value:123456789)], ["aa","bbb","cccc"], [true, "766", NSNull(), 655231.9823]] as NSArray) - XCTAssertTrue(json[0] == [1,2.123456,123456789]) + let json: JSON = JSON ([[NSNumber(value: 1), NSNumber(value: 2.123456), NSNumber(value: 123456789)], ["aa", "bbb", "cccc"], [true, "766", NSNull(), 655231.9823]] as NSArray) + XCTAssertTrue(json[0] == [1, 2.123456, 123456789]) XCTAssertEqual(json[0][1].double!, 2.123456) XCTAssertTrue(json[0][2] == 123456789) XCTAssertTrue(json[1][0] == "aa") - XCTAssertTrue(json[1] == ["aa","bbb","cccc"]) + XCTAssertTrue(json[1] == ["aa", "bbb", "cccc"]) XCTAssertTrue(json[2][0] == true) XCTAssertTrue(json[2][1] == "766") - XCTAssertTrue(json[[2,1]] == "766") + XCTAssertTrue(json[[2, 1]] == "766") XCTAssertEqual(json[2][2], JSON(NSNull())) - XCTAssertEqual(json[2,2], JSON(NSNull())) + XCTAssertEqual(json[2, 2], JSON(NSNull())) XCTAssertEqual(json[2][3], JSON(655231.9823)) - XCTAssertEqual(json[2,3], JSON(655231.9823)) - XCTAssertEqual(json[[2,3]], JSON(655231.9823)) + XCTAssertEqual(json[2, 3], JSON(655231.9823)) + XCTAssertEqual(json[[2, 3]], JSON(655231.9823)) } - + func testOutOfBounds() { - let json:JSON = JSON ([[NSNumber(value:1),NSNumber(value:2.123456),NSNumber(value:123456789)], ["aa","bbb","cccc"], [true, "766", NSNull(), 655231.9823]] as NSArray) + let json: JSON = JSON ([[NSNumber(value: 1), NSNumber(value: 2.123456), NSNumber(value: 123456789)], ["aa", "bbb", "cccc"], [true, "766", NSNull(), 655231.9823]] as NSArray) XCTAssertEqual(json[9], JSON.null) - XCTAssertEqual(json[-2].error!.code, ErrorIndexOutOfBounds) - XCTAssertEqual(json[6].error!.code, ErrorIndexOutOfBounds) + XCTAssertEqual(json[-2].error, SwiftyJSONError.indexOutOfBounds) + XCTAssertEqual(json[6].error, SwiftyJSONError.indexOutOfBounds) XCTAssertEqual(json[9][8], JSON.null) - XCTAssertEqual(json[8][7].error!.code, ErrorIndexOutOfBounds) - XCTAssertEqual(json[8,7].error!.code, ErrorIndexOutOfBounds) - XCTAssertEqual(json[999].error!.code, ErrorIndexOutOfBounds) + XCTAssertEqual(json[8][7].error, SwiftyJSONError.indexOutOfBounds) + XCTAssertEqual(json[8, 7].error, SwiftyJSONError.indexOutOfBounds) + XCTAssertEqual(json[999].error, SwiftyJSONError.indexOutOfBounds) } - + func testErrorWrongType() { let json = JSON(12345) XCTAssertEqual(json[9], JSON.null) - XCTAssertEqual(json[9].error!.code, ErrorWrongType) - XCTAssertEqual(json[8][7].error!.code, ErrorWrongType) + XCTAssertEqual(json[9].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json[8][7].error, SwiftyJSONError.wrongType) XCTAssertEqual(json["name"], JSON.null) - XCTAssertEqual(json["name"].error!.code, ErrorWrongType) - XCTAssertEqual(json[0]["name"].error!.code, ErrorWrongType) - XCTAssertEqual(json["type"]["name"].error!.code, ErrorWrongType) - XCTAssertEqual(json["name"][99].error!.code, ErrorWrongType) - XCTAssertEqual(json[1,"Value"].error!.code, ErrorWrongType) - XCTAssertEqual(json[1, 2,"Value"].error!.code, ErrorWrongType) - XCTAssertEqual(json[[1, 2,"Value"]].error!.code, ErrorWrongType) + XCTAssertEqual(json["name"].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json[0]["name"].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json["type"]["name"].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json["name"][99].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json[1, "Value"].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json[1, 2, "Value"].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json[[1, 2, "Value"]].error, SwiftyJSONError.wrongType) } - + func testErrorNotExist() { - let json:JSON = ["name":"NAME", "age":15] + let json: JSON = ["name": "NAME", "age": 15] XCTAssertEqual(json["Type"], JSON.null) - XCTAssertEqual(json["Type"].error!.code, ErrorNotExist) - XCTAssertEqual(json["Type"][1].error!.code, ErrorNotExist) - XCTAssertEqual(json["Type", 1].error!.code, ErrorNotExist) - XCTAssertEqual(json["Type"]["Value"].error!.code, ErrorNotExist) - XCTAssertEqual(json["Type","Value"].error!.code, ErrorNotExist) + XCTAssertEqual(json["Type"].error, SwiftyJSONError.notExist) + XCTAssertEqual(json["Type"][1].error, SwiftyJSONError.notExist) + XCTAssertEqual(json["Type", 1].error, SwiftyJSONError.notExist) + XCTAssertEqual(json["Type"]["Value"].error, SwiftyJSONError.notExist) + XCTAssertEqual(json["Type", "Value"].error, SwiftyJSONError.notExist) } - + func testMultilevelGetter() { - let json:JSON = [[[[["one":1]]]]] + let json: JSON = [[[[["one": 1]]]]] XCTAssertEqual(json[[0, 0, 0, 0, "one"]].int!, 1) XCTAssertEqual(json[0, 0, 0, 0, "one"].int!, 1) XCTAssertEqual(json[0][0][0][0]["one"].int!, 1) } - + func testMultilevelSetter1() { - var json:JSON = [[[[["num":1]]]]] + var json: JSON = [[[[["num": 1]]]]] json[0, 0, 0, 0, "num"] = 2 XCTAssertEqual(json[[0, 0, 0, 0, "num"]].intValue, 2) json[0, 0, 0, 0, "num"] = JSON.null XCTAssertEqual(json[0, 0, 0, 0, "num"].null!, NSNull()) json[0, 0, 0, 0, "num"] = 100.009 XCTAssertEqual(json[0][0][0][0]["num"].doubleValue, 100.009) - json[[0, 0, 0, 0]] = ["name":"Jack"] - XCTAssertEqual(json[0,0,0,0,"name"].stringValue, "Jack") + json[[0, 0, 0, 0]] = ["name": "Jack"] + XCTAssertEqual(json[0, 0, 0, 0, "name"].stringValue, "Jack") XCTAssertEqual(json[0][0][0][0]["name"].stringValue, "Jack") - XCTAssertEqual(json[[0,0,0,0,"name"]].stringValue, "Jack") - json[[0,0,0,0,"name"]].string = "Mike" - XCTAssertEqual(json[0,0,0,0,"name"].stringValue, "Mike") - let path:[JSONSubscriptType] = [0,0,0,0,"name"] + XCTAssertEqual(json[[0, 0, 0, 0, "name"]].stringValue, "Jack") + json[[0, 0, 0, 0, "name"]].string = "Mike" + XCTAssertEqual(json[0, 0, 0, 0, "name"].stringValue, "Mike") + let path: [JSONSubscriptType] = [0, 0, 0, 0, "name"] json[path].string = "Jim" XCTAssertEqual(json[path].stringValue, "Jim") } - + func testMultilevelSetter2() { - var json:JSON = ["user":["id":987654, "info":["name":"jack","email":"jack@gmail.com"], "feeds":[98833,23443,213239,23232]]] - json["user","info","name"] = "jim" - XCTAssertEqual(json["user","id"], 987654) - XCTAssertEqual(json["user","info","name"], "jim") - XCTAssertEqual(json["user","info","email"], "jack@gmail.com") - XCTAssertEqual(json["user","feeds"], [98833,23443,213239,23232]) - json["user","info","email"] = "jim@hotmail.com" - XCTAssertEqual(json["user","id"], 987654) - XCTAssertEqual(json["user","info","name"], "jim") - XCTAssertEqual(json["user","info","email"], "jim@hotmail.com") - XCTAssertEqual(json["user","feeds"], [98833,23443,213239,23232]) - json["user","info"] = ["name":"tom","email":"tom@qq.com"] - XCTAssertEqual(json["user","id"], 987654) - XCTAssertEqual(json["user","info","name"], "tom") - XCTAssertEqual(json["user","info","email"], "tom@qq.com") - XCTAssertEqual(json["user","feeds"], [98833,23443,213239,23232]) - json["user","feeds"] = [77323,2313,4545,323] - XCTAssertEqual(json["user","id"], 987654) - XCTAssertEqual(json["user","info","name"], "tom") - XCTAssertEqual(json["user","info","email"], "tom@qq.com") - XCTAssertEqual(json["user","feeds"], [77323,2313,4545,323]) + var json: JSON = ["user": ["id": 987654, "info": ["name": "jack", "email": "jack@gmail.com"], "feeds": [98833, 23443, 213239, 23232]]] + json["user", "info", "name"] = "jim" + XCTAssertEqual(json["user", "id"], 987654) + XCTAssertEqual(json["user", "info", "name"], "jim") + XCTAssertEqual(json["user", "info", "email"], "jack@gmail.com") + XCTAssertEqual(json["user", "feeds"], [98833, 23443, 213239, 23232]) + json["user", "info", "email"] = "jim@hotmail.com" + XCTAssertEqual(json["user", "id"], 987654) + XCTAssertEqual(json["user", "info", "name"], "jim") + XCTAssertEqual(json["user", "info", "email"], "jim@hotmail.com") + XCTAssertEqual(json["user", "feeds"], [98833, 23443, 213239, 23232]) + json["user", "info"] = ["name": "tom", "email": "tom@qq.com"] + XCTAssertEqual(json["user", "id"], 987654) + XCTAssertEqual(json["user", "info", "name"], "tom") + XCTAssertEqual(json["user", "info", "email"], "tom@qq.com") + XCTAssertEqual(json["user", "feeds"], [98833, 23443, 213239, 23232]) + json["user", "feeds"] = [77323, 2313, 4545, 323] + XCTAssertEqual(json["user", "id"], 987654) + XCTAssertEqual(json["user", "info", "name"], "tom") + XCTAssertEqual(json["user", "info", "email"], "tom@qq.com") + XCTAssertEqual(json["user", "feeds"], [77323, 2313, 4545, 323]) } } diff --git a/Tests/SwiftyJSONTests/Tests.json b/Tests/SwiftJSONTests/Tests.json similarity index 100% rename from Tests/SwiftyJSONTests/Tests.json rename to Tests/SwiftJSONTests/Tests.json diff --git a/Tests/SwiftyJSONTests/NestedJSONTests.swift b/Tests/SwiftyJSONTests/NestedJSONTests.swift deleted file mode 100644 index 5c75def7..00000000 --- a/Tests/SwiftyJSONTests/NestedJSONTests.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// NestedJSONTests.swift -// SwiftyJSON -// -// Created by Hector Matos on 9/27/16. -// -// - -import XCTest -import SwiftyJSON - -class NestedJSONTests: XCTestCase { - let family: JSON = [ - "names" : [ - "Brooke Abigail Matos", - "Rowan Danger Matos" - ], - "motto" : "Hey, I don't know about you, but I'm feeling twenty-two! So, release the KrakenDev!" - ] - - func testTopLevelNestedJSON() { - let nestedJSON: JSON = [ - "family" : family - ] - XCTAssertNotNil(try? nestedJSON.rawData()) - } - - func testDeeplyNestedJSON() { - let nestedFamily: JSON = [ - "count": 1, - "families": [ - [ - "isACoolFamily" : true, - "family" : [ - "hello" : family - ] - ] - ] - ] - XCTAssertNotNil(try? nestedFamily.rawData()) - } -} diff --git a/scripts/carthage.sh b/scripts/carthage.sh deleted file mode 100755 index aeee56ae..00000000 --- a/scripts/carthage.sh +++ /dev/null @@ -1,2 +0,0 @@ -carthage build --no-skip-current -carthage archive SwiftyJSON