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..a3816d45 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,23 @@ +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: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_16.4.app + + - name: Build + run: xcrun swift build --build-tests + + - name: Run tests + run: xcrun swift test \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8841a69a..2731938e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,6 @@ DerivedData #CocoaPods Pods -*.xcscheme + +#Carthage +Carthage/Build 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/.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/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..082b0247 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,450 @@ +# Change Log + +## [Unreleased](https://github.com/SwiftyJSON/SwiftyJSON/tree/HEAD) + +[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) + +- 'AnyObject' is not convertible to 'String'; did you mean to use 'as!' to force downcast? [\#218](https://github.com/SwiftyJSON/SwiftyJSON/issues/218) + +- pod -\> SwiftyJSON \(2.1.3\) is out-of-date if we compare it to the version mentioned in README.md file. [\#212](https://github.com/SwiftyJSON/SwiftyJSON/issues/212) + +- 无法获取到 2.2版本的 [\#211](https://github.com/SwiftyJSON/SwiftyJSON/issues/211) + +- Publish Podspec for version 2.2.0 [\#210](https://github.com/SwiftyJSON/SwiftyJSON/issues/210) + +- dropping elements? or am I doing something wrong? [\#209](https://github.com/SwiftyJSON/SwiftyJSON/issues/209) + +- Not working with Swift 1.2 [\#208](https://github.com/SwiftyJSON/SwiftyJSON/issues/208) + +- 在 Mac 项目里用 Carthage 无法编译 [\#193](https://github.com/SwiftyJSON/SwiftyJSON/issues/193) + +- 使用中发现解析效率比较低 [\#190](https://github.com/SwiftyJSON/SwiftyJSON/issues/190) + +- Looks like it will require a change of "as"es to "as!" for Swift 1.2... [\#150](https://github.com/SwiftyJSON/SwiftyJSON/issues/150) + +- No response appeared [\#118](https://github.com/SwiftyJSON/SwiftyJSON/issues/118) + +- Swift Optional Values from JSON [\#116](https://github.com/SwiftyJSON/SwiftyJSON/issues/116) + +- It seems not easy to manipulate an array or dictionary? [\#110](https://github.com/SwiftyJSON/SwiftyJSON/issues/110) + +**Merged pull requests:** + +- Fix for xcode 6.3..1 issue [\#224](https://github.com/SwiftyJSON/SwiftyJSON/pull/224) ([datomnurdin](https://github.com/datomnurdin)) + +- Update the first two examples snippets [\#223](https://github.com/SwiftyJSON/SwiftyJSON/pull/223) ([kmikael](https://github.com/kmikael)) + +- Allow .number to parse number from string instead of just numberValue [\#219](https://github.com/SwiftyJSON/SwiftyJSON/pull/219) ([yonaskolb](https://github.com/yonaskolb)) + +- Fixed spelling and grammar mistakes in README.md. Made some swift syntax... [\#214](https://github.com/SwiftyJSON/SwiftyJSON/pull/214) ([pRizz](https://github.com/pRizz)) + +- Added a function to deep merge a JSON object into another JSON object... [\#725](https://github.com/SwiftyJSON/SwiftyJSON/pull/725) ([danielkiedrowski](https://github.com/danielkiedrowski)) + +## [2.2.0](https://github.com/SwiftyJSON/SwiftyJSON/tree/2.2.0) (2015-04-13) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.1.3...2.2.0) + +**Closed issues:** + +- init doesn't set type correctly [\#206](https://github.com/SwiftyJSON/SwiftyJSON/issues/206) + +- SwitfyJSON breaks with update to iOS 8.3 & Xcode 6.3 [\#200](https://github.com/SwiftyJSON/SwiftyJSON/issues/200) + +- 'NSString?' is not convertible to 'String?' error with Swift 1.2 [\#198](https://github.com/SwiftyJSON/SwiftyJSON/issues/198) + +- I can't install it by carthage [\#181](https://github.com/SwiftyJSON/SwiftyJSON/issues/181) + +- Can't compare JSON to Float [\#171](https://github.com/SwiftyJSON/SwiftyJSON/issues/171) + +- extend data to results [\#160](https://github.com/SwiftyJSON/SwiftyJSON/issues/160) + +- Create JSON From String [\#159](https://github.com/SwiftyJSON/SwiftyJSON/issues/159) + +- No Cocoapods support for iOS 7 [\#151](https://github.com/SwiftyJSON/SwiftyJSON/issues/151) + +- Update to Swift 1.2 [\#148](https://github.com/SwiftyJSON/SwiftyJSON/issues/148) + +- Url slashes ' / ' are being replaced with ' \/ ' [\#145](https://github.com/SwiftyJSON/SwiftyJSON/issues/145) + +- Issues when using carthage [\#144](https://github.com/SwiftyJSON/SwiftyJSON/issues/144) + +- Can not convert \[JSON\] to JSON [\#143](https://github.com/SwiftyJSON/SwiftyJSON/issues/143) + +- \[!\] Unable to find a specification for `SwiftyJSON \(= 2.1.3\)` [\#141](https://github.com/SwiftyJSON/SwiftyJSON/issues/141) + +- Deployment target iOS 7 or iOS 8? [\#131](https://github.com/SwiftyJSON/SwiftyJSON/issues/131) + +- Cocoapods support [\#126](https://github.com/SwiftyJSON/SwiftyJSON/issues/126) + +**Merged pull requests:** + +- Only building tests for testing [\#207](https://github.com/SwiftyJSON/SwiftyJSON/pull/207) ([spanage](https://github.com/spanage)) + +- Added compatibility with Swift 1.2. [\#204](https://github.com/SwiftyJSON/SwiftyJSON/pull/204) ([jankaltoun](https://github.com/jankaltoun)) + +- Fix for issue \#200 [\#203](https://github.com/SwiftyJSON/SwiftyJSON/pull/203) ([chschu](https://github.com/chschu)) + +- Updated to Swift 1.2 [\#202](https://github.com/SwiftyJSON/SwiftyJSON/pull/202) ([scottdelly](https://github.com/scottdelly)) + +- Updated to Swift 1.2 [\#201](https://github.com/SwiftyJSON/SwiftyJSON/pull/201) ([scottdelly](https://github.com/scottdelly)) + +- Update to Swift 1.2 [\#199](https://github.com/SwiftyJSON/SwiftyJSON/pull/199) ([kimdv](https://github.com/kimdv)) + +- Should not get subscript from AnyObject. [\#196](https://github.com/SwiftyJSON/SwiftyJSON/pull/196) ([Candyroot](https://github.com/Candyroot)) + +- Update for Swift 1.2 [\#195](https://github.com/SwiftyJSON/SwiftyJSON/pull/195) ([justinmakaila](https://github.com/justinmakaila)) + +- Update README.md [\#194](https://github.com/SwiftyJSON/SwiftyJSON/pull/194) ([manijshrestha](https://github.com/manijshrestha)) + +- Optimize the code to avoid useless casts to swift arrays. [\#188](https://github.com/SwiftyJSON/SwiftyJSON/pull/188) ([mirion](https://github.com/mirion)) + +- Fixed the buildable name in the OSX scheme [\#187](https://github.com/SwiftyJSON/SwiftyJSON/pull/187) ([cnoon](https://github.com/cnoon)) + +- Updated code signing identities for OSX target and tests [\#186](https://github.com/SwiftyJSON/SwiftyJSON/pull/186) ([cnoon](https://github.com/cnoon)) + +- Fix int overflow compile error [\#178](https://github.com/SwiftyJSON/SwiftyJSON/pull/178) ([mono0926](https://github.com/mono0926)) + +- Fixed a bug when accessing a value directly via a string subscript when the current object is a dictionary [\#176](https://github.com/SwiftyJSON/SwiftyJSON/pull/176) ([JosephDuffy](https://github.com/JosephDuffy)) + +- Better support for carthage users [\#174](https://github.com/SwiftyJSON/SwiftyJSON/pull/174) ([rromanchuk](https://github.com/rromanchuk)) + +- Fixes a 32bit/64bit issue. [\#172](https://github.com/SwiftyJSON/SwiftyJSON/pull/172) ([enhorn](https://github.com/enhorn)) + +- Update README for new Cocoapods [\#170](https://github.com/SwiftyJSON/SwiftyJSON/pull/170) ([joelparkerhenderson](https://github.com/joelparkerhenderson)) + +- Fixed a crash when entering json\["NotExistPath"\] [\#167](https://github.com/SwiftyJSON/SwiftyJSON/pull/167) ([ybeapps](https://github.com/ybeapps)) + +- Adding Swift 1.2 support [\#158](https://github.com/SwiftyJSON/SwiftyJSON/pull/158) ([Jasdev](https://github.com/Jasdev)) + +- Fix issues with the OS X target and scheme [\#156](https://github.com/SwiftyJSON/SwiftyJSON/pull/156) ([rastersize](https://github.com/rastersize)) + +- Fix issues with the OS X target and scheme [\#155](https://github.com/SwiftyJSON/SwiftyJSON/pull/155) ([rastersize](https://github.com/rastersize)) + +- Remove SwiftJSON.xcodeproj/xcuserdata [\#154](https://github.com/SwiftyJSON/SwiftyJSON/pull/154) ([rastersize](https://github.com/rastersize)) + +- Change to not build test when building iOS framework target \[Xcode 6.3 + external tools\] [\#153](https://github.com/SwiftyJSON/SwiftyJSON/pull/153) ([rastersize](https://github.com/rastersize)) + +- Fix tests not building for 32-bit \[Xcode 6.3\] [\#152](https://github.com/SwiftyJSON/SwiftyJSON/pull/152) ([rastersize](https://github.com/rastersize)) + +- Swift 1.2 compatibility fixes [\#149](https://github.com/SwiftyJSON/SwiftyJSON/pull/149) ([darrarski](https://github.com/darrarski)) + +- \[README.md\] Setter for JSON array should use arrayObject not array [\#146](https://github.com/SwiftyJSON/SwiftyJSON/pull/146) ([lwu](https://github.com/lwu)) + +- add missing ` in comments [\#142](https://github.com/SwiftyJSON/SwiftyJSON/pull/142) ([zhxnlai](https://github.com/zhxnlai)) + +- Fix README.md nested example [\#139](https://github.com/SwiftyJSON/SwiftyJSON/pull/139) ([watsonbox](https://github.com/watsonbox)) + +- Shared OSX Scheme. OSX target fixes. [\#138](https://github.com/SwiftyJSON/SwiftyJSON/pull/138) ([haveahennessy](https://github.com/haveahennessy)) + +- Casting to NSDictionary instead of \[String : AnyObject\] [\#137](https://github.com/SwiftyJSON/SwiftyJSON/pull/137) ([clwkct](https://github.com/clwkct)) + +- Update README.md [\#136](https://github.com/SwiftyJSON/SwiftyJSON/pull/136) ([esbenvb](https://github.com/esbenvb)) + +- Update README.md [\#135](https://github.com/SwiftyJSON/SwiftyJSON/pull/135) ([esbenvb](https://github.com/esbenvb)) + +- Fixed the broken Carthage OS X Support. [\#134](https://github.com/SwiftyJSON/SwiftyJSON/pull/134) ([remaerd](https://github.com/remaerd)) + +- Prefixed "SequenceType" extension with Module name [\#124](https://github.com/SwiftyJSON/SwiftyJSON/pull/124) ([ravero](https://github.com/ravero)) + +- Code cleaning [\#123](https://github.com/SwiftyJSON/SwiftyJSON/pull/123) ([wiruzx](https://github.com/wiruzx)) + +## [2.1.3](https://github.com/SwiftyJSON/SwiftyJSON/tree/2.1.3) (2015-01-10) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.1.2...2.1.3) + +**Closed issues:** + +- Cannot install using Carthage [\#122](https://github.com/SwiftyJSON/SwiftyJSON/issues/122) + +- Use of unresolved identifier 'dataFromNetworking' [\#112](https://github.com/SwiftyJSON/SwiftyJSON/issues/112) + +- I can't parse out the string like "{a:5}" [\#109](https://github.com/SwiftyJSON/SwiftyJSON/issues/109) + +- Cocoapods integration [\#108](https://github.com/SwiftyJSON/SwiftyJSON/issues/108) + +- Compile Error In Loop Array [\#107](https://github.com/SwiftyJSON/SwiftyJSON/issues/107) + +- Support for Carthage [\#105](https://github.com/SwiftyJSON/SwiftyJSON/issues/105) + +**Merged pull requests:** + +- Minor grammar fixes to README [\#128](https://github.com/SwiftyJSON/SwiftyJSON/pull/128) ([johngoren](https://github.com/johngoren)) + +- Updated because podspec is now available... [\#127](https://github.com/SwiftyJSON/SwiftyJSON/pull/127) ([johngoren](https://github.com/johngoren)) + +- Fix access modificator of isEmpty property [\#121](https://github.com/SwiftyJSON/SwiftyJSON/pull/121) ([wiruzx](https://github.com/wiruzx)) + +- Make framework extension friendly [\#119](https://github.com/SwiftyJSON/SwiftyJSON/pull/119) ([technomage](https://github.com/technomage)) + +- add a new way to access Json [\#117](https://github.com/SwiftyJSON/SwiftyJSON/pull/117) ([zhanghao111111111](https://github.com/zhanghao111111111)) + +- fix the typos on the code snippets and the links in the TOC on README [\#115](https://github.com/SwiftyJSON/SwiftyJSON/pull/115) ([floydpink](https://github.com/floydpink)) + +- Use Mac' codesign identities for OSX targets [\#114](https://github.com/SwiftyJSON/SwiftyJSON/pull/114) ([max-potapov](https://github.com/max-potapov)) + +## [2.1.2](https://github.com/SwiftyJSON/SwiftyJSON/tree/2.1.2) (2014-12-13) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.1.1...2.1.2) + +**Closed issues:** + +- Why can't we parse a rawString back to json object? [\#101](https://github.com/SwiftyJSON/SwiftyJSON/issues/101) + +- Have a Piece of Code that might be of Value to SwiftyJSon [\#97](https://github.com/SwiftyJSON/SwiftyJSON/issues/97) + +- build osx application \(command line tool\) with swiftyjson error [\#96](https://github.com/SwiftyJSON/SwiftyJSON/issues/96) + +- 这个应该是bug吧,支持的不是很够 [\#95](https://github.com/SwiftyJSON/SwiftyJSON/issues/95) + +- Length of an array [\#90](https://github.com/SwiftyJSON/SwiftyJSON/issues/90) + +- Compilation error [\#89](https://github.com/SwiftyJSON/SwiftyJSON/issues/89) + +- Can't set value [\#88](https://github.com/SwiftyJSON/SwiftyJSON/issues/88) + +- Examples with AFHTTPSessionManager? [\#86](https://github.com/SwiftyJSON/SwiftyJSON/issues/86) + +**Merged pull requests:** + +- Update README.md to add Carthage instructions [\#113](https://github.com/SwiftyJSON/SwiftyJSON/pull/113) ([justinmakaila](https://github.com/justinmakaila)) + +- Improve init performance for dictionaries and arrays [\#111](https://github.com/SwiftyJSON/SwiftyJSON/pull/111) ([avorobjov](https://github.com/avorobjov)) + +- Fix NSNumber != func [\#106](https://github.com/SwiftyJSON/SwiftyJSON/pull/106) ([briankracoff](https://github.com/briankracoff)) + +- Carthage Support [\#104](https://github.com/SwiftyJSON/SwiftyJSON/pull/104) ([justinmakaila](https://github.com/justinmakaila)) + +- Added read option for date strings [\#103](https://github.com/SwiftyJSON/SwiftyJSON/pull/103) ([Dschee](https://github.com/Dschee)) + +- Add Podspec \(Correct mblsha podspec\) [\#100](https://github.com/SwiftyJSON/SwiftyJSON/pull/100) ([ValCapri](https://github.com/ValCapri)) + +- Add podspec + make it work as a framework [\#99](https://github.com/SwiftyJSON/SwiftyJSON/pull/99) ([mblsha](https://github.com/mblsha)) + +- Adding new Feature: JsonMapper [\#98](https://github.com/SwiftyJSON/SwiftyJSON/pull/98) ([Drogenix](https://github.com/Drogenix)) + +- Change recommendation for Alamofire integration [\#92](https://github.com/SwiftyJSON/SwiftyJSON/pull/92) ([JonathanPorta](https://github.com/JonathanPorta)) + +## [2.1.1](https://github.com/SwiftyJSON/SwiftyJSON/tree/2.1.1) (2014-11-12) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.1.0...2.1.1) + +**Closed issues:** + +- NSDictionary to json string to json object [\#93](https://github.com/SwiftyJSON/SwiftyJSON/issues/93) + +- Error: use of unresolved identifier dataFromNetworking [\#82](https://github.com/SwiftyJSON/SwiftyJSON/issues/82) + +- Type \[SubscriptType\] Does not conform to protocol 'StringLiteralConvertible' [\#81](https://github.com/SwiftyJSON/SwiftyJSON/issues/81) + +- Doesn't conform literal protocols [\#80](https://github.com/SwiftyJSON/SwiftyJSON/issues/80) + +- iOS 8.1 compatability [\#79](https://github.com/SwiftyJSON/SwiftyJSON/issues/79) + +- Xcode 6.1 Compatibility [\#78](https://github.com/SwiftyJSON/SwiftyJSON/issues/78) + +- Problem with xCode 6.1 [\#76](https://github.com/SwiftyJSON/SwiftyJSON/issues/76) + +- Compilation errors [\#75](https://github.com/SwiftyJSON/SwiftyJSON/issues/75) + +**Merged pull requests:** + +- Renamed type 'Unknow' to 'Unknown' [\#94](https://github.com/SwiftyJSON/SwiftyJSON/pull/94) ([franklsf95](https://github.com/franklsf95)) + +- Added OSX target. [\#91](https://github.com/SwiftyJSON/SwiftyJSON/pull/91) ([carloslozano](https://github.com/carloslozano)) + +- Add date ,dateValue [\#87](https://github.com/SwiftyJSON/SwiftyJSON/pull/87) ([muukii0803](https://github.com/muukii0803)) + +- Add parse JSON Date [\#85](https://github.com/SwiftyJSON/SwiftyJSON/pull/85) ([ShineWu](https://github.com/ShineWu)) + +- Update README.md [\#84](https://github.com/SwiftyJSON/SwiftyJSON/pull/84) ([johngoren](https://github.com/johngoren)) + +- Update README.md for typos [\#83](https://github.com/SwiftyJSON/SwiftyJSON/pull/83) ([johngoren](https://github.com/johngoren)) + +## [2.1.0](https://github.com/SwiftyJSON/SwiftyJSON/tree/2.1.0) (2014-10-19) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/2.0.0...2.1.0) + +**Closed issues:** + +- 32bit test failures [\#71](https://github.com/SwiftyJSON/SwiftyJSON/issues/71) + +- Trouble getting string representation [\#70](https://github.com/SwiftyJSON/SwiftyJSON/issues/70) + +- JSON keep null [\#69](https://github.com/SwiftyJSON/SwiftyJSON/issues/69) + +- Update .pbxproj to Deployment Target 8.0 [\#66](https://github.com/SwiftyJSON/SwiftyJSON/issues/66) + +- Looping not working [\#64](https://github.com/SwiftyJSON/SwiftyJSON/issues/64) + +**Merged pull requests:** + +- Get number from string in JSON.number [\#74](https://github.com/SwiftyJSON/SwiftyJSON/pull/74) ([yonaskolb](https://github.com/yonaskolb)) + +- Update SwiftyJSON.swift [\#73](https://github.com/SwiftyJSON/SwiftyJSON/pull/73) ([MaddTheSane](https://github.com/MaddTheSane)) + +- Generating Raw JSON Strings [\#72](https://github.com/SwiftyJSON/SwiftyJSON/pull/72) ([lesmuc](https://github.com/lesmuc)) + +- Making SourceKit not freak out about self.object.count being called [\#68](https://github.com/SwiftyJSON/SwiftyJSON/pull/68) ([Noobish1](https://github.com/Noobish1)) + +- Added support for Xcode 6.1 GM Seed 2. [\#65](https://github.com/SwiftyJSON/SwiftyJSON/pull/65) ([rosskimes](https://github.com/rosskimes)) + +## [2.0.0](https://github.com/SwiftyJSON/SwiftyJSON/tree/2.0.0) (2014-10-08) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/1.1.0...2.0.0) + +**Closed issues:** + +- JSON to NSData [\#62](https://github.com/SwiftyJSON/SwiftyJSON/issues/62) + +- Updating a json [\#60](https://github.com/SwiftyJSON/SwiftyJSON/issues/60) + +**Merged pull requests:** + +- Update for new features \[Issue \#60\] [\#63](https://github.com/SwiftyJSON/SwiftyJSON/pull/63) ([tangplin](https://github.com/tangplin)) + +## [1.1.0](https://github.com/SwiftyJSON/SwiftyJSON/tree/1.1.0) (2014-10-02) + +[Full Changelog](https://github.com/SwiftyJSON/SwiftyJSON/compare/1.0.0...1.1.0) + +**Closed issues:** + +- Long time to parse this json [\#57](https://github.com/SwiftyJSON/SwiftyJSON/issues/57) + +**Merged pull requests:** + +- Merge develop [\#59](https://github.com/SwiftyJSON/SwiftyJSON/pull/59) ([tangplin](https://github.com/tangplin)) + +- Added SwiftyJSON lazy wrapping [\#58](https://github.com/SwiftyJSON/SwiftyJSON/pull/58) ([k06a](https://github.com/k06a)) + +## [1.0.0](https://github.com/SwiftyJSON/SwiftyJSON/tree/1.0.0) (2014-09-26) + +**Implemented enhancements:** + +- JNumber should be Number not double [\#8](https://github.com/SwiftyJSON/SwiftyJSON/issues/8) + +- Separate implementations of protocols [\#5](https://github.com/SwiftyJSON/SwiftyJSON/issues/5) + +**Fixed bugs:** + +- JNumber should be Number not double [\#8](https://github.com/SwiftyJSON/SwiftyJSON/issues/8) + +- Fails to compile on Beta2 [\#1](https://github.com/SwiftyJSON/SwiftyJSON/issues/1) + +**Closed issues:** + +- No such module "SwiftyJSON" [\#49](https://github.com/SwiftyJSON/SwiftyJSON/issues/49) + +- how to transfer JSONValue object to Dictionary object? [\#48](https://github.com/SwiftyJSON/SwiftyJSON/issues/48) + +- JSONValue in @objc [\#47](https://github.com/SwiftyJSON/SwiftyJSON/issues/47) + +- SwiftyJSON.swift:331:22: Use of undeclared type 'BooleanType' [\#46](https://github.com/SwiftyJSON/SwiftyJSON/issues/46) + +- Problem converting JSONValue to AnyObject [\#44](https://github.com/SwiftyJSON/SwiftyJSON/issues/44) + +- Can't use SwiftyJSON as part of a public API within a framework [\#42](https://github.com/SwiftyJSON/SwiftyJSON/issues/42) + +- how to add JSONValue object into exist JSONValue [\#40](https://github.com/SwiftyJSON/SwiftyJSON/issues/40) + +- Doesn't work in BETA 6 [\#39](https://github.com/SwiftyJSON/SwiftyJSON/issues/39) + +- Can't access property [\#38](https://github.com/SwiftyJSON/SwiftyJSON/issues/38) + +- Couldn't Compile and Run [\#37](https://github.com/SwiftyJSON/SwiftyJSON/issues/37) + +- Array index out of range [\#35](https://github.com/SwiftyJSON/SwiftyJSON/issues/35) + +- Iterating through a JSON response [\#32](https://github.com/SwiftyJSON/SwiftyJSON/issues/32) + +- NSNull in an array is discarded [\#25](https://github.com/SwiftyJSON/SwiftyJSON/issues/25) + +- Updating Dictionary [\#24](https://github.com/SwiftyJSON/SwiftyJSON/issues/24) + +- SourcekitService Terminated Issue [\#22](https://github.com/SwiftyJSON/SwiftyJSON/issues/22) + +- Code does not compile in iOS 8 Beta 3. [\#17](https://github.com/SwiftyJSON/SwiftyJSON/issues/17) + +- How to use .count [\#14](https://github.com/SwiftyJSON/SwiftyJSON/issues/14) + +- Add to cocoapods [\#12](https://github.com/SwiftyJSON/SwiftyJSON/issues/12) + +- String parsing [\#9](https://github.com/SwiftyJSON/SwiftyJSON/issues/9) + +- Cocoapods integration [\#4](https://github.com/SwiftyJSON/SwiftyJSON/issues/4) + +- How do I verify SwiftyJSON workS? [\#2](https://github.com/SwiftyJSON/SwiftyJSON/issues/2) + +**Merged pull requests:** + +- Revert "Added rawObject method for unwrapping JSONValue enum to objects" [\#56](https://github.com/SwiftyJSON/SwiftyJSON/pull/56) ([tangplin](https://github.com/tangplin)) + +- set the default JSONReadingOptions to .AllowFragments [\#55](https://github.com/SwiftyJSON/SwiftyJSON/pull/55) ([tangplin](https://github.com/tangplin)) + +- Fix Unit Test [\#54](https://github.com/SwiftyJSON/SwiftyJSON/pull/54) ([lingoer](https://github.com/lingoer)) + +- Add NSError to Null type [\#53](https://github.com/SwiftyJSON/SwiftyJSON/pull/53) ([lingoer](https://github.com/lingoer)) + +- Refactor! [\#51](https://github.com/SwiftyJSON/SwiftyJSON/pull/51) ([tangplin](https://github.com/tangplin)) + +- Rename LISCENSE to LICENSE [\#50](https://github.com/SwiftyJSON/SwiftyJSON/pull/50) ([fixe](https://github.com/fixe)) + +- Added rawObject method for unwrapping JSONValue enum to objects [\#45](https://github.com/SwiftyJSON/SwiftyJSON/pull/45) ([k06a](https://github.com/k06a)) + +- made JSONValue public for usage in framework APIs [\#43](https://github.com/SwiftyJSON/SwiftyJSON/pull/43) ([Dschee](https://github.com/Dschee)) + +- Adding public/private modifiers so that SwiftyJSON can be used as a framework [\#41](https://github.com/SwiftyJSON/SwiftyJSON/pull/41) ([jansabbe](https://github.com/jansabbe)) + +- Rename LISCENSE to LICENSE [\#36](https://github.com/SwiftyJSON/SwiftyJSON/pull/36) ([kriswallsmith](https://github.com/kriswallsmith)) + +- Fix for Xcode 6 beta 5 changes [\#34](https://github.com/SwiftyJSON/SwiftyJSON/pull/34) ([FahimF](https://github.com/FahimF)) + +- Use BooleanType instead of LogicValue for Beta 5 [\#33](https://github.com/SwiftyJSON/SwiftyJSON/pull/33) ([venables](https://github.com/venables)) + +- Support for JSON as string [\#31](https://github.com/SwiftyJSON/SwiftyJSON/pull/31) ([bsvingen](https://github.com/bsvingen)) + +- Support building JSON messages in code. [\#30](https://github.com/SwiftyJSON/SwiftyJSON/pull/30) ([johnno1962](https://github.com/johnno1962)) + +- Update project to include access modifiers from Xcode beta 4. [\#29](https://github.com/SwiftyJSON/SwiftyJSON/pull/29) ([Baltoli](https://github.com/Baltoli)) + +- jsonvalue now conforms to sequence protocol for array values [\#28](https://github.com/SwiftyJSON/SwiftyJSON/pull/28) ([NatashaTheRobot](https://github.com/NatashaTheRobot)) + +- updated array and dictionary syntax for beta3 [\#27](https://github.com/SwiftyJSON/SwiftyJSON/pull/27) ([NatashaTheRobot](https://github.com/NatashaTheRobot)) + +- Update for Beta 4: exposing JSONValue with public [\#26](https://github.com/SwiftyJSON/SwiftyJSON/pull/26) ([NachoSoto](https://github.com/NachoSoto)) + +- SourceKitService Termination issue fix [\#23](https://github.com/SwiftyJSON/SwiftyJSON/pull/23) ([ipraba](https://github.com/ipraba)) + +- Add percent escaping to URL string [\#21](https://github.com/SwiftyJSON/SwiftyJSON/pull/21) ([romanroibu](https://github.com/romanroibu)) + +- Converting JSON objects to string is fixed [\#20](https://github.com/SwiftyJSON/SwiftyJSON/pull/20) ([bkase](https://github.com/bkase)) + +- JSONValue can be inited via string [\#19](https://github.com/SwiftyJSON/SwiftyJSON/pull/19) ([bkase](https://github.com/bkase)) + +- Updated to remove errors in Xcode Beta 3 [\#18](https://github.com/SwiftyJSON/SwiftyJSON/pull/18) ([krishpop](https://github.com/krishpop)) + +- add first and last in JSONValue, add string to double, int etc. [\#16](https://github.com/SwiftyJSON/SwiftyJSON/pull/16) ([tangplin](https://github.com/tangplin)) + +- add a "url" property to JSONValue [\#15](https://github.com/SwiftyJSON/SwiftyJSON/pull/15) ([kyoh](https://github.com/kyoh)) + +- Some typo fixes [\#13](https://github.com/SwiftyJSON/SwiftyJSON/pull/13) ([gregbarbosa](https://github.com/gregbarbosa)) + +- Separate protocols implementation, refactor prettyString composing [\#6](https://github.com/SwiftyJSON/SwiftyJSON/pull/6) ([garnett](https://github.com/garnett)) + +- Add project with both OSX/iOS module targets [\#3](https://github.com/SwiftyJSON/SwiftyJSON/pull/3) ([garnett](https://github.com/garnett)) + + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj new file mode 100644 index 00000000..e0a5e55e --- /dev/null +++ b/Example/Example.xcodeproj/project.pbxproj @@ -0,0 +1,359 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 04733F521D92E6ED002E3A99 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04733F511D92E6ED002E3A99 /* SwiftyJSON.framework */; }; + 04733F531D92E6ED002E3A99 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 04733F511D92E6ED002E3A99 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + A82A1C1F19D926B8009A653D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A82A1C1E19D926B8009A653D /* AppDelegate.swift */; }; + A82A1C2419D926B8009A653D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A82A1C2219D926B8009A653D /* Main.storyboard */; }; + A82A1C2619D926B8009A653D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A82A1C2519D926B8009A653D /* Images.xcassets */; }; + A82A1C2919D926B8009A653D /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A82A1C2719D926B8009A653D /* LaunchScreen.xib */; }; + A82A1C4019D94AE5009A653D /* SwiftyJSONTests.json in Resources */ = {isa = PBXBuildFile; fileRef = A82A1C3F19D94AE5009A653D /* SwiftyJSONTests.json */; }; + A82A1C5619D95606009A653D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A82A1C5519D95606009A653D /* ViewController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + A82A1C5419D94E97009A653D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 04733F531D92E6ED002E3A99 /* SwiftyJSON.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 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 = ""; }; + A82A1C1E19D926B8009A653D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A82A1C2319D926B8009A653D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + A82A1C2519D926B8009A653D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + A82A1C2819D926B8009A653D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + A82A1C3F19D94AE5009A653D /* SwiftyJSONTests.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SwiftyJSONTests.json; sourceTree = ""; }; + A82A1C5519D95606009A653D /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A82A1C1619D926B8009A653D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 04733F521D92E6ED002E3A99 /* SwiftyJSON.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A82A1C1019D926B8009A653D = { + isa = PBXGroup; + children = ( + 04733F511D92E6ED002E3A99 /* SwiftyJSON.framework */, + 04294C501BE5A9DE00D0397E /* Playground.playground */, + A82A1C1B19D926B8009A653D /* Example */, + A82A1C1A19D926B8009A653D /* Products */, + ); + sourceTree = ""; + }; + A82A1C1A19D926B8009A653D /* Products */ = { + isa = PBXGroup; + children = ( + A82A1C1919D926B8009A653D /* Example.app */, + ); + name = Products; + sourceTree = ""; + }; + A82A1C1B19D926B8009A653D /* Example */ = { + isa = PBXGroup; + children = ( + A82A1C3F19D94AE5009A653D /* SwiftyJSONTests.json */, + A82A1C1E19D926B8009A653D /* AppDelegate.swift */, + A82A1C5519D95606009A653D /* ViewController.swift */, + A82A1C2219D926B8009A653D /* Main.storyboard */, + A82A1C2519D926B8009A653D /* Images.xcassets */, + A82A1C2719D926B8009A653D /* LaunchScreen.xib */, + A82A1C1C19D926B8009A653D /* Supporting Files */, + ); + path = Example; + sourceTree = ""; + }; + A82A1C1C19D926B8009A653D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + A82A1C1D19D926B8009A653D /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A82A1C1819D926B8009A653D /* Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = A82A1C3819D926B8009A653D /* Build configuration list for PBXNativeTarget "Example" */; + buildPhases = ( + A82A1C1519D926B8009A653D /* Sources */, + A82A1C1619D926B8009A653D /* Frameworks */, + A82A1C1719D926B8009A653D /* Resources */, + A82A1C5419D94E97009A653D /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Example; + productName = Example; + productReference = A82A1C1919D926B8009A653D /* Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A82A1C1119D926B8009A653D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = swiftyjson; + TargetAttributes = { + A82A1C1819D926B8009A653D = { + CreatedOnToolsVersion = 6.0.1; + LastSwiftMigration = 1020; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = A82A1C1419D926B8009A653D /* Build configuration list for PBXProject "Example" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A82A1C1019D926B8009A653D; + productRefGroup = A82A1C1A19D926B8009A653D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A82A1C1819D926B8009A653D /* Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A82A1C1719D926B8009A653D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A82A1C2419D926B8009A653D /* Main.storyboard in Resources */, + A82A1C2919D926B8009A653D /* LaunchScreen.xib in Resources */, + A82A1C2619D926B8009A653D /* Images.xcassets in Resources */, + A82A1C4019D94AE5009A653D /* SwiftyJSONTests.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A82A1C1519D926B8009A653D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A82A1C5619D95606009A653D /* ViewController.swift in Sources */, + A82A1C1F19D926B8009A653D /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + A82A1C2219D926B8009A653D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A82A1C2319D926B8009A653D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + A82A1C2719D926B8009A653D /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + A82A1C2819D926B8009A653D /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A82A1C3619D926B8009A653D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A82A1C3719D926B8009A653D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + A82A1C3919D926B8009A653D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Example/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + A82A1C3A19D926B8009A653D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Example/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A82A1C1419D926B8009A653D /* Build configuration list for PBXProject "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A82A1C3619D926B8009A653D /* Debug */, + A82A1C3719D926B8009A653D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A82A1C3819D926B8009A653D /* Build configuration list for PBXNativeTarget "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A82A1C3919D926B8009A653D /* Debug */, + A82A1C3A19D926B8009A653D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A82A1C1119D926B8009A653D /* Project object */; +} diff --git a/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Example/Example/AppDelegate.swift b/Example/Example/AppDelegate.swift new file mode 100644 index 00000000..c4236b1d --- /dev/null +++ b/Example/Example/AppDelegate.swift @@ -0,0 +1,50 @@ +// AppDelegate.swift +// +// Copyright (c) 2014 - 2016 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 UIKit +import SwiftyJSON + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + 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 = try JSON(data: data) + viewController.json = json + } catch { + viewController.json = JSON.null + } + } else { + viewController.json = JSON.null + } + + return true + } +} diff --git a/Example/Example/Base.lproj/LaunchScreen.xib b/Example/Example/Base.lproj/LaunchScreen.xib new file mode 100644 index 00000000..43a0234f --- /dev/null +++ b/Example/Example/Base.lproj/LaunchScreen.xib @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Example/Base.lproj/Main.storyboard b/Example/Example/Base.lproj/Main.storyboard new file mode 100644 index 00000000..0db932d7 --- /dev/null +++ b/Example/Example/Base.lproj/Main.storyboard @@ -0,0 +1,85 @@ + + + + + + + + + + HelveticaNeue + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..1d060ed2 --- /dev/null +++ b/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json b/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 00000000..d8c7ca1b --- /dev/null +++ b/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,52 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "retina4", + "filename" : "Default@2x.png", + "minimum-system-version" : "7.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Example/Images.xcassets/LaunchImage.launchimage/Default@2x.png b/Example/Example/Images.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 00000000..3604134f Binary files /dev/null and b/Example/Example/Images.xcassets/LaunchImage.launchimage/Default@2x.png differ diff --git a/Example/Example/Info.plist b/Example/Example/Info.plist new file mode 100644 index 00000000..40c6215d --- /dev/null +++ b/Example/Example/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/SwiftyJSONTests/SwiftyJSONTests.json b/Example/Example/SwiftyJSONTests.json similarity index 100% rename from SwiftyJSONTests/SwiftyJSONTests.json rename to Example/Example/SwiftyJSONTests.json diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift new file mode 100644 index 00000000..8f297a7b --- /dev/null +++ b/Example/Example/ViewController.swift @@ -0,0 +1,92 @@ +// ViewController.swift +// +// Copyright (c) 2014 - 2016 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 UIKit +import SwiftyJSON + +class ViewController: UITableViewController { + + var json: JSON = JSON.null + + // MARK: - Table view data source + + override func viewDidLoad() { + title = "SwiftyJSON(\(json.type))" + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch self.json.type { + case .array, .dictionary: + return self.json.count + default: + return 1 + } + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "JSONCell", for: indexPath) as UITableViewCell + + let row = indexPath.row + + switch self.json.type { + case .array: + cell.textLabel?.text = "\(row)" + cell.detailTextLabel?.text = self.json.arrayValue.description + case .dictionary: + let key: Any = Array(self.json.dictionaryValue.keys)[row] + let value = self.json[key as! String] + cell.textLabel?.text = "\(key)" + cell.detailTextLabel?.text = value.description + default: + cell.textLabel?.text = "" + cell.detailTextLabel?.text = self.json.description + } + + return cell + } + + // MARK: - Navigation + + override func prepare(for segue: UIStoryboardSegue, sender: Any!) { + + var nextController: UIViewController? + nextController = segue.destination + + if let indexPath = self.tableView.indexPathForSelectedRow { + let row = indexPath.row + var nextJson: JSON = JSON.null + switch self.json.type { + case .array: + nextJson = self.json[row] + case .dictionary where row < self.json.dictionaryValue.count: + let key = Array(self.json.dictionaryValue.keys)[row] + if let value = self.json.dictionary?[key] { + nextJson = value + } + default: + print("") + } + (nextController as! ViewController).json = nextJson + print(nextJson) + } + } +} diff --git a/Example/Playground.playground/Contents.swift b/Example/Playground.playground/Contents.swift new file mode 100644 index 00000000..7542d181 --- /dev/null +++ b/Example/Playground.playground/Contents.swift @@ -0,0 +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 +*/ +import SwiftyJSON +import Foundation + +var jsonData: Data? + +if let file = Bundle.main.path(forResource: "SwiftyJSONTests", ofType: "json") { + jsonData = try? Data(contentsOf: URL(fileURLWithPath: file)) +} else { + print("Fail") +} + +let jsonObject = try JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments) + +let jsonString = String(data: jsonData!, encoding: .utf8) + +/*: +## Usage + +### Initialization + +*/ + +let json1 = try? JSON(data: jsonData!) +/*: +or +*/ +let json2 = JSON(jsonObject) +/*: +or +*/ +let dataFromString = jsonString?.data(using: .utf8) +let json3 = try? JSON(data: dataFromString!) + +/*: +### Subscript +*/ +// Example json +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 +json["array"][0].double + +// Getting an array of string from a JSON Array +let arrayOfString = json["users"].arrayValue.map({$0["info"]["name"]}) +print(arrayOfString) + +// Getting a string from a JSON Dictionary +json["users"][0]["info"]["name"].stringValue + +// Getting a string using a path to the element +let path = ["users", 1, "info", "name"] as [JSONSubscriptType] +var name = json["users", 1, "info", "name"].string + +// With a custom way +let keys: [JSONSubscriptType] = ["users", 1, "info", "name"] +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.. + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE index a7af1968..68e3fd74 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Ruoyu Fu +Copyright (c) 2017 Ruoyu Fu Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..fb026e55 --- /dev/null +++ b/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version:6.0 +import PackageDescription + +let package = Package( + name: "SwiftyJSON", + products: [ + .library(name: "SwiftyJSON", targets: ["SwiftyJSON"]) + ], + targets: [ + .target(name: "SwiftyJSON", + dependencies: [], + resources: [ + .copy("PrivacyInfo.xcprivacy") + ] + ), + .testTarget( + name: "SwiftJSONTests", + dependencies: ["SwiftyJSON"], + resources: [ + .copy("Tests.json") + ] + ) + ] +) diff --git a/README.md b/README.md index 60466ab1..a6f3037a 100644 --- a/README.md +++ b/README.md @@ -1,194 +1,620 @@ -#SwiftyJSON +# SwiftyJSON + +[![CI](https://github.com/SwiftyJSON/SwiftyJSON/actions/workflows/ci.yml/badge.svg)](https://github.com/SwiftyJSON/SwiftyJSON/actions/workflows/ci.yml) + +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![CocoaPods](https://img.shields.io/cocoapods/v/SwiftyJSON.svg) ![Platform](https://img.shields.io/badge/platforms-iOS%208.0%20%7C%20macOS%2010.10%20%7C%20tvOS%209.0%20%7C%20watchOS%203.0-F28D00.svg) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) + SwiftyJSON makes it easy to deal with JSON data in Swift. -##Why is the typical JSON handling in Swift NOT good? -Swift is very strict about types, it's good while explicit typing left us little chance to make mistakes. -But while dealing with things that naturally implicit about types such as JSON, it's painful. - -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) - -```JSON - -[ - { - ...... - "text": "just another test", - ...... - "user": { - "name": "OAuth Dancer", - "favourites_count": 7, - "entities": { - "url": { - "urls": [ - { - "expanded_url": null, - "url": "http://bit.ly/oauth-dancer", - "indices": [ - 0, - 26 - ], - "display_url": null - } - ] - } - ...... - }, - "in_reply_to_screen_name": null, - }, - ......] - -``` + +1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good) +2. [Requirements](#requirements) +3. [Integration](#integration) +4. [Usage](#usage) + - [Initialization](#initialization) + - [Subscript](#subscript) + - [Loop](#loop) + - [Error](#error) + - [Optional getter](#optional-getter) + - [Non-optional getter](#non-optional-getter) + - [Setter](#setter) + - [Raw object](#raw-object) + - [Literal convertibles](#literal-convertibles) + - [Merging](#merging) + - [Removing elements](#removing-elements) +5. [Work with Alamofire](#work-with-alamofire) +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://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline)). The code would look like this: ```swift - -let jsonObject : AnyObject! = NSJSONSerialization.JSONObjectWithData(dataFromTwitter, options: NSJSONReadingOptions.MutableContainers, error: nil) -if let statusesArray = jsonObject as? NSArray{ - if let aStatus = statusesArray[0] as? NSDictionary{ - if let user = aStatus["user"] as? NSDictionary{ - if let userName = user["name"] as? NSDictionary{ - //Finally We Got The Name - - } - } - } +if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]], + let user = statusesArray[0]["user"] as? [String: Any], + let username = user["name"] as? String { + // Finally we got the username } - ``` It's not good. -Even if we use optional chaining, it would also cause a mess: +Even if we use optional chaining, it would be messy: ```swift - -let jsonObject : AnyObject! = NSJSONSerialization.JSONObjectWithData(dataFromTwitter, options: NSJSONReadingOptions.MutableContainers, error: nil) -if let userName = (((jsonObject as? NSArray)?[0] as? NSDictionary)?["user"] as? NSDictionary)?["name"]{ - //What A disaster above +if let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]], + let username = (JSONObject[0]["user"] as? [String: Any])?["name"] as? String { + // There's our username } - ``` -An unreadable mess for something like this should really be simple! - -##SwiftyJSON +An unreadable mess--for something that should really be simple! With SwiftyJSON all you have to do is: ```swift - -let json = JSON(data: dataFromNetworking) -if let userName = json[0]["user"]["name"].string{ +let json = try? JSON(data: dataFromNetworking) +if let userName = json[0]["user"]["name"].string { //Now you got your value } - ``` -And don't worry about the Optional Wrapping thing, it's done for you automatically +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 - println(json[999999]["wrong_key"]["wrong_name"]) + print(result.error) } - ``` ## Requirements -- iOS 7.0+ / Mac OS X 10.9+ -- Xcode 6.0 +- iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+ +- 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`: + +```ruby +platform :ios, '8.0' +use_frameworks! + +target 'MyApp' do + pod 'SwiftyJSON', '~> 4.0' +end +``` + +#### 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" ~> 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", + dependencies: [ + .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"), + ] +) +``` +Then run `swift build` whenever you get prepared. + +#### Manually (iOS 7+, OS X 10.9+) + +To use this library in your project manually you may: + +1. for Projects, just drag SwiftyJSON.swift to the project tree +2. for Workspaces, include the whole SwiftyJSON.xcodeproj ## Usage -####Initialization +#### Initialization + ```swift -let json = JSON(data: dataFromNetworking) +import SwiftyJSON ``` + ```swift -let json = JSON(object: jsonObject) +let json = try? JSON(data: dataFromNetworking) ``` +Or -####Use the optional getter ```swift -//NSNumber +let json = JSON(jsonObject) +``` +Or + +```swift +if let dataFromString = jsonString.data(using: .utf8, allowLossyConversion: false) { + let json = JSON(data: dataFromString) +} +``` + +#### Subscript + +```swift +// Getting a double from a JSON Array +let name = json[0].double +``` + +```swift +// Getting an array of string from a JSON Array +let arrayNames = json["users"].arrayValue.map {$0["name"].stringValue} +``` + +```swift +// Getting a string from a JSON Dictionary +let name = json["name"].stringValue +``` + +```swift +// Getting a string using a path to the element +let path: [JSONSubscriptType] = [1,"list",2,"name"] +let name = json[path].string +// Just the same +let name = json[1]["list"][2]["name"].string +// Alternatively +let name = json[1,"list",2,"name"].string +``` + +```swift +// With a hard way +let name = json[].string +``` + +```swift +// With a custom way +let keys:[JSONSubscriptType] = [1,"list",2,"name"] +let name = json[keys].string +``` + +#### Loop + +```swift +// If json is .Dictionary +for (key,subJson):(String, JSON) in json { + // Do something you want +} +``` + +*The first element is always a String, even if the JSON is an Array* + +```swift +// If json is .Array +// The `index` is 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 ``` -###Get the raw object from JSON +#### Setter + +```swift +json["name"] = JSON("new-name") +json[0] = JSON(1) +``` + +```swift +json["id"].int = 1234567890 +json["coordinate"].double = 8766.766 +json["name"].string = "Jack" +json.arrayObject = [1,2,3,4] +json.dictionaryObject = ["name":"Jack", "age":25] +``` + +#### Raw object + +```swift +let rawObject: Any = json.object +``` + ```swift -let json = JSON(data: dataFromNetworking) -if let jsonObject: AnyObject = json.object { - // do something +let rawValue: Any = json.rawValue +``` + +```swift +//convert the JSON to raw NSData +do { + let rawData = try json.rawData() + //Do something you want +} catch { + print("Error \(error)") +} +``` + +```swift +//convert the JSON to a raw String +if let rawString = json.rawString() { + //Do something you want } else { - // print the error - println(json) + print("json.rawString is nil") +} +``` + +#### Existence + +```swift +// shows you whether value specified in JSON or not +if json["name"].exists() +``` + +#### Literal convertibles + +For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/) + +```swift +// StringLiteralConvertible +let json: JSON = "I'm a json" +``` + +```swift +// IntegerLiteralConvertible +let json: JSON = 12345 +``` + +```swift +// BooleanLiteralConvertible +let json: JSON = true +``` + +```swift +// FloatLiteralConvertible +let json: JSON = 2.8765 +``` + +```swift +// DictionaryLiteralConvertible +let json: JSON = ["I":"am", "a":"json"] +``` + +```swift +// ArrayLiteralConvertible +let json: JSON = ["I", "am", "a", "json"] +``` + +```swift +// 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 +``` + +```swift +// With subscript in dictionary +var json: JSON = ["name": "Jack", "age": 25] +json["name"] = "Mike" +json["age"] = "25" // It's OK to set String +json["address"] = "L.A." // Add the "address": "L.A." in json +``` + +```swift +// 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" +let path: [JSONSubscriptType] = ["list",3,"what"] +json[path] = "that" +``` + +```swift +// With other JSON objects +let user: JSON = ["username" : "Steve", "password": "supersecurepassword"] +let auth: JSON = [ + "user": user.object, // use user.object instead of just user + "apikey": "supersecretapitoken" +] +``` + +#### Merging + +It is possible to merge one JSON into another JSON. Merging a JSON into another JSON adds all non existing values to the original JSON which are only present in the `other` JSON. + +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.dictionary` both JSON-values are getting merged the same way the encapsulating JSON is merged. + +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. + +```swift +let original: JSON = [ + "first_name": "John", + "age": 20, + "skills": ["Coding", "Reading"], + "address": [ + "street": "Front St", + "zip": "12345", + ] +] + +let update: JSON = [ + "last_name": "Doe", + "age": 21, + "skills": ["Writing"], + "address": [ + "zip": "12342", + "city": "New York City" + ] +] + +let updated = original.merge(with: update) +// [ +// "first_name": "John", +// "last_name": "Doe", +// "age": 21, +// "skills": ["Coding", "Reading", "Writing"], +// "address": [ +// "street": "Front St", +// "zip": "12342", +// "city": "New York City" +// ] +// ] +``` + + +#### 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" + } + } } ``` -##Integration +This also works for nested dictionaries: + +```swift +object["two"]["foods"].dictionaryObject?.removeValue(forKey: "breakfast") +``` + +```json +{ + "one" : { + "color" : "blue" + }, + "two" : { + "city" : "tokyo", + "foods" : { + "lunch" : "sushi" + } + } +} +``` -CocoaPods is not fully supported for Swift yet, to use this library in your project you should: +## String representation +There are two options available: +- use the default Swift one +- use a custom one that will handle optionals well and represent `nil` as `"null"`: +```swift +let dict = ["1":2, "2":"two", "3": nil] as [String: Any?] +let json = JSON(dict) +let representation = json.rawString(options: [.castNilToNSNull: true]) +// representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null} +``` -1. for Projects just drag SwiftyJSON.swift to the project tree -2. for Workspaces you may include the whole SwiftyJSON.xcodeproj as suggested by @garnett +## Work with [Alamofire](https://github.com/Alamofire/Alamofire) +SwiftyJSON nicely wraps the result of the Alamofire JSON response handler: -##Work with Alamofire +```swift +Alamofire.request(url, method: .get).validate().responseJSON { response in + switch response.result { + case .success(let value): + let json = JSON(value) + print("JSON: \(json)") + case .failure(let error): + print(error) + } +} +``` + +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)") + } +} + +``` -To use Alamofire and SwiftyJSON, try [Alamofire-SwiftyJSON](https://github.com/SwiftyJSON/Alamofire-SwiftyJSON). +## SwiftyJSON Model Generator +Tools to generate SwiftyJSON Models +* [JSON Export](https://github.com/Ahmed-Ali/JSONExport) diff --git a/SwiftyJSON/Info.plist b/Source/Info-iOS.plist similarity index 92% rename from SwiftyJSON/Info.plist rename to Source/Info-iOS.plist index 34eb412b..78122054 100644 --- a/SwiftyJSON/Info.plist +++ b/Source/Info-iOS.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - Aemaeth.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Source/Info-macOS.plist b/Source/Info-macOS.plist new file mode 100644 index 00000000..d3de8eef --- /dev/null +++ b/Source/Info-macOS.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Source/Info-tvOS.plist b/Source/Info-tvOS.plist new file mode 100644 index 00000000..8d348099 --- /dev/null +++ b/Source/Info-tvOS.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + UIRequiredDeviceCapabilities + + arm64 + + + diff --git a/Source/Info-watchOS.plist b/Source/Info-watchOS.plist new file mode 100644 index 00000000..78122054 --- /dev/null +++ b/Source/Info-watchOS.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + 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/SwiftyJSON/SwiftyJSON.h b/Source/SwiftyJSON/SwiftyJSON.h similarity index 96% rename from SwiftyJSON/SwiftyJSON.h rename to Source/SwiftyJSON/SwiftyJSON.h index 74552a7c..d69a7643 100644 --- a/SwiftyJSON/SwiftyJSON.h +++ b/Source/SwiftyJSON/SwiftyJSON.h @@ -1,6 +1,6 @@ // SwiftyJSON.h // -// Copyright (c) 2014 Ruoyu Fu, Pinglin Tang +// 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 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 new file mode 100644 index 00000000..dd091231 --- /dev/null +++ b/SwiftyJSON.podspec @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = "SwiftyJSON" + 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 = "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/SwiftyJSON/*.swift" + s.resource_bundles = {'SwiftyJSON' => ['Source/SwiftyJSON/PrivacyInfo.xcprivacy']} +end diff --git a/SwiftyJSON.xcodeproj/project.pbxproj b/SwiftyJSON.xcodeproj/project.pbxproj index 4c795026..3c325ac2 100644 --- a/SwiftyJSON.xcodeproj/project.pbxproj +++ b/SwiftyJSON.xcodeproj/project.pbxproj @@ -6,17 +6,90 @@ 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 */; }; + 1B587CC81DDE04790012D8DB /* MergeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B587CC41DDE04360012D8DB /* MergeTests.swift */; }; 2E4FEFE119575BE100351305 /* SwiftyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4FEFE019575BE100351305 /* SwiftyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2E4FEFE719575BE100351305 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E4FEFDB19575BE100351305 /* SwiftyJSON.framework */; }; - 2E4FF00D19575CE600351305 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E4FF00219575CE600351305 /* SwiftyJSON.framework */; }; - 2E4FF01C19575D1100351305 /* SwiftyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4FEFE019575BE100351305 /* SwiftyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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, ); }; }; + 9C459EF51A910361008C9A41 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */; }; + 9C459EF81A9103C1008C9A41 /* Tests.json in Resources */ = {isa = PBXBuildFile; fileRef = A885D1DA19CFCFF0002FD4C3 /* Tests.json */; }; + 9C459EF91A9103C1008C9A41 /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */; }; + 9C459EFA1A9103C1008C9A41 /* BaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */; }; + 9C459EFB1A9103C1008C9A41 /* SequenceTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E319E3C2A600CDE086 /* SequenceTypeTests.swift */; }; + 9C459EFC1A9103C1008C9A41 /* PrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C4A019E37FC600ADCC3D /* PrintableTests.swift */; }; + 9C459EFD1A9103C1008C9A41 /* SubscriptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */; }; + 9C459EFE1A9103C1008C9A41 /* LiteralConvertibleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */; }; + 9C459EFF1A9103C1008C9A41 /* RawRepresentableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */; }; + 9C459F001A9103C1008C9A41 /* ComparableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E519E3DF7800CDE086 /* ComparableTests.swift */; }; + 9C459F011A9103C1008C9A41 /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E919E43C0700CDE086 /* StringTests.swift */; }; + 9C459F021A9103C1008C9A41 /* NumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E719E439DA00CDE086 /* NumberTests.swift */; }; + 9C459F031A9103C1008C9A41 /* RawTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A863BE2719EED46F0092A41F /* RawTests.swift */; }; + 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 */; }; - A885D1D219CF1EE6002FD4C3 /* SwiftyJSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A885D1D119CF1EE6002FD4C3 /* SwiftyJSONTests.swift */; }; - A885D1D319CF1EE6002FD4C3 /* SwiftyJSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A885D1D119CF1EE6002FD4C3 /* SwiftyJSONTests.swift */; }; - A885D1D519CF223F002FD4C3 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */; }; - A885D1DC19CFCFF0002FD4C3 /* SwiftyJSONTests.json in Resources */ = {isa = PBXBuildFile; fileRef = A885D1DA19CFCFF0002FD4C3 /* SwiftyJSONTests.json */; }; - A885D1DD19CFCFF0002FD4C3 /* SwiftyJSONTests.json in Resources */ = {isa = PBXBuildFile; fileRef = A885D1DA19CFCFF0002FD4C3 /* SwiftyJSONTests.json */; }; + A8580F791BCF5C5B00DA927B /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7236B4F61BAC14150020529B /* SwiftyJSON.framework */; }; + A8580F801BCF69A000DA927B /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */; }; + A8580F811BCF69A000DA927B /* BaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */; }; + A8580F821BCF69A000DA927B /* SequenceTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E319E3C2A600CDE086 /* SequenceTypeTests.swift */; }; + A8580F831BCF69A000DA927B /* PrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C4A019E37FC600ADCC3D /* PrintableTests.swift */; }; + A8580F841BCF69A000DA927B /* SubscriptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */; }; + A8580F851BCF69A000DA927B /* LiteralConvertibleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */; }; + A8580F861BCF69A000DA927B /* RawRepresentableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */; }; + A8580F871BCF69A000DA927B /* ComparableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E519E3DF7800CDE086 /* ComparableTests.swift */; }; + A8580F881BCF69A000DA927B /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E919E43C0700CDE086 /* StringTests.swift */; }; + A8580F891BCF69A000DA927B /* NumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E719E439DA00CDE086 /* NumberTests.swift */; }; + A8580F8A1BCF69A000DA927B /* RawTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A863BE2719EED46F0092A41F /* RawTests.swift */; }; + A8580F8B1BCF69A000DA927B /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8B19E51D6500540692 /* DictionaryTests.swift */; }; + A8580F8C1BCF69A000DA927B /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8D19E52F4200540692 /* ArrayTests.swift */; }; + A863BE2819EED46F0092A41F /* RawTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A863BE2719EED46F0092A41F /* RawTests.swift */; }; + A86BAA0E19EBC32B009EAAEB /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */; }; + A87080E419E3C2A600CDE086 /* SequenceTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E319E3C2A600CDE086 /* SequenceTypeTests.swift */; }; + A87080E619E3DF7800CDE086 /* ComparableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E519E3DF7800CDE086 /* ComparableTests.swift */; }; + A87080E819E439DA00CDE086 /* NumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E719E439DA00CDE086 /* NumberTests.swift */; }; + A87080EA19E43C0700CDE086 /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87080E919E43C0700CDE086 /* StringTests.swift */; }; + A885D1D219CF1EE6002FD4C3 /* BaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */; }; + A885D1DC19CFCFF0002FD4C3 /* Tests.json in Resources */ = {isa = PBXBuildFile; fileRef = A885D1DA19CFCFF0002FD4C3 /* Tests.json */; }; + A8B66C8C19E51D6500540692 /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8B19E51D6500540692 /* DictionaryTests.swift */; }; + A8B66C8E19E52F4200540692 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8B66C8D19E52F4200540692 /* ArrayTests.swift */; }; + E4D7CCE01B9465A700EE7221 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */; }; + E4D7CCE31B9465A700EE7221 /* SwiftyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4FEFE019575BE100351305 /* SwiftyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -27,26 +100,58 @@ remoteGlobalIDString = 2E4FEFDA19575BE100351305; remoteInfo = SwiftyJSON; }; - 2E4FF00E19575CE600351305 /* PBXContainerItemProxy */ = { + 9C7DFC671A9102BD005AA3F7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 2E4FEFD219575BE100351305 /* Project object */; proxyType = 1; - remoteGlobalIDString = 2E4FF00119575CE600351305; - remoteInfo = "SwiftyJSON-OSX"; + remoteGlobalIDString = 9C7DFC5A1A9102BD005AA3F7; + remoteInfo = "SwiftyJSON OSX"; + }; + A8580F7A1BCF5C5B00DA927B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2E4FEFD219575BE100351305 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7236B4EC1BAC14150020529B; + remoteInfo = "SwiftyJSON tvOS"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 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.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 2E4FEFE019575BE100351305 /* SwiftyJSON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftyJSON.h; sourceTree = ""; }; - 2E4FEFE619575BE100351305 /* SwiftyJSONTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyJSONTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 2E4FEFEC19575BE100351305 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 2E4FF00219575CE600351305 /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2E4FF00C19575CE600351305 /* SwiftyJSON-OSXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftyJSON-OSXTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyJSON.swift; sourceTree = ""; }; - A885D1D119CF1EE6002FD4C3 /* SwiftyJSONTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyJSONTests.swift; sourceTree = ""; }; - A885D1DA19CFCFF0002FD4C3 /* SwiftyJSONTests.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SwiftyJSONTests.json; sourceTree = ""; }; + 2E4FEFDF19575BE100351305 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; 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; 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-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 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; 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; 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 */ /* Begin PBXFrameworksBuildPhase section */ @@ -65,18 +170,40 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FEFFE19575CE600351305 /* Frameworks */ = { + 7236B4EF1BAC14150020529B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C7DFC571A9102BD005AA3F7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C7DFC621A9102BD005AA3F7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9C7DFC661A9102BD005AA3F7 /* SwiftyJSON.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FF00919575CE600351305 /* Frameworks */ = { + A8580F711BCF5C5B00DA927B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A8580F791BCF5C5B00DA927B /* SwiftyJSON.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E4D7CCE11B9465A700EE7221 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2E4FF00D19575CE600351305 /* SwiftyJSON.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -86,8 +213,8 @@ 2E4FEFD119575BE100351305 = { isa = PBXGroup; children = ( - 2E4FEFDD19575BE100351305 /* SwiftyJSON */, - 2E4FEFEA19575BE100351305 /* SwiftyJSONTests */, + 2E4FEFDD19575BE100351305 /* Source */, + 2E4FEFEA19575BE100351305 /* Tests */, 2E4FEFDC19575BE100351305 /* Products */, ); sourceTree = ""; @@ -96,45 +223,71 @@ isa = PBXGroup; children = ( 2E4FEFDB19575BE100351305 /* SwiftyJSON.framework */, - 2E4FEFE619575BE100351305 /* SwiftyJSONTests.xctest */, - 2E4FF00219575CE600351305 /* SwiftyJSON.framework */, - 2E4FF00C19575CE600351305 /* SwiftyJSON-OSXTests.xctest */, + 2E4FEFE619575BE100351305 /* SwiftyJSON iOS Tests.xctest */, + 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */, + 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON macOS Tests.xctest */, + E4D7CCE81B9465A700EE7221 /* SwiftyJSON.framework */, + 7236B4F61BAC14150020529B /* SwiftyJSON.framework */, + A8580F741BCF5C5B00DA927B /* SwiftyJSON tvOS Tests.xctest */, ); name = Products; sourceTree = ""; }; - 2E4FEFDD19575BE100351305 /* SwiftyJSON */ = { + 2E4FEFDD19575BE100351305 /* Source */ = { isa = PBXGroup; children = ( 2E4FEFE019575BE100351305 /* SwiftyJSON.h */, A8491E1D19CD6DAE00CCFAE6 /* SwiftyJSON.swift */, 2E4FEFDE19575BE100351305 /* Supporting Files */, ); - path = SwiftyJSON; + path = Source; sourceTree = ""; }; 2E4FEFDE19575BE100351305 /* Supporting Files */ = { isa = PBXGroup; children = ( - 2E4FEFDF19575BE100351305 /* Info.plist */, + A1DE64C52BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy */, + 2E4FEFDF19575BE100351305 /* Info-iOS.plist */, + 030B6CDC1A6E171D00C2D4F1 /* Info-macOS.plist */, + E4D7CCE91B9465A800EE7221 /* Info-watchOS.plist */, + 7236B4F71BAC14150020529B /* Info-tvOS.plist */, ); name = "Supporting Files"; sourceTree = ""; }; - 2E4FEFEA19575BE100351305 /* SwiftyJSONTests */ = { + 2E4FEFEA19575BE100351305 /* Tests */ = { isa = PBXGroup; children = ( - A885D1DA19CFCFF0002FD4C3 /* SwiftyJSONTests.json */, - A885D1D119CF1EE6002FD4C3 /* SwiftyJSONTests.swift */, + 1B587CC41DDE04360012D8DB /* MergeTests.swift */, + A86BAA0D19EBC32B009EAAEB /* PerformanceTests.swift */, + A885D1D119CF1EE6002FD4C3 /* BaseTests.swift */, + 5DD502901D9B21810004C112 /* NestedJSONTests.swift */, + A87080E319E3C2A600CDE086 /* SequenceTypeTests.swift */, + A819C4A019E37FC600ADCC3D /* PrintableTests.swift */, + A819C49E19E2EE5B00ADCC3D /* SubscriptTests.swift */, + A819C49619E1A7DD00ADCC3D /* LiteralConvertibleTests.swift */, + A819C49819E1B10300ADCC3D /* RawRepresentableTests.swift */, + A87080E519E3DF7800CDE086 /* ComparableTests.swift */, + A87080E919E43C0700CDE086 /* StringTests.swift */, + A87080E719E439DA00CDE086 /* NumberTests.swift */, + A863BE2719EED46F0092A41F /* RawTests.swift */, + A8B66C8B19E51D6500540692 /* DictionaryTests.swift */, + A830A6941E5B2DD8001D7F6D /* MutabilityTests.swift */, + A8B66C8D19E52F4200540692 /* ArrayTests.swift */, + 712921EE2004E4EB00DA6340 /* CodableTests.swift */, 2E4FEFEB19575BE100351305 /* Supporting Files */, ); - path = SwiftyJSONTests; + name = Tests; + path = Tests/SwiftJSONTests; sourceTree = ""; }; 2E4FEFEB19575BE100351305 /* Supporting Files */ = { isa = PBXGroup; children = ( - 2E4FEFEC19575BE100351305 /* Info.plist */, + A885D1DA19CFCFF0002FD4C3 /* Tests.json */, + A82A1C0D19D922DC009A653D /* Info-iOS.plist */, + 9C459EF61A9103B1008C9A41 /* Info-macOS.plist */, + A8580F781BCF5C5B00DA927B /* Info-tvOS.plist */, ); name = "Supporting Files"; sourceTree = ""; @@ -150,38 +303,54 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FEFFF19575CE600351305 /* Headers */ = { + 7236B4F01BAC14150020529B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 7236B4F11BAC14150020529B /* SwiftyJSON.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C7DFC581A9102BD005AA3F7 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 2E4FF01C19575D1100351305 /* SwiftyJSON.h in Headers */, + 9C459EF41A910334008C9A41 /* SwiftyJSON.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E4D7CCE21B9465A700EE7221 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E4D7CCE31B9465A700EE7221 /* SwiftyJSON.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 2E4FEFDA19575BE100351305 /* SwiftyJSON */ = { + 2E4FEFDA19575BE100351305 /* SwiftyJSON iOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 2E4FEFF119575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */; + buildConfigurationList = 2E4FEFF119575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON iOS" */; buildPhases = ( + 2E4FEFD819575BE100351305 /* Headers */, 2E4FEFD619575BE100351305 /* Sources */, 2E4FEFD719575BE100351305 /* Frameworks */, - 2E4FEFD819575BE100351305 /* Headers */, 2E4FEFD919575BE100351305 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = SwiftyJSON; + name = "SwiftyJSON iOS"; productName = SwiftyJSON; productReference = 2E4FEFDB19575BE100351305 /* SwiftyJSON.framework */; productType = "com.apple.product-type.framework"; }; - 2E4FEFE519575BE100351305 /* SwiftyJSONTests */ = { + 2E4FEFE519575BE100351305 /* SwiftyJSON iOS Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 2E4FEFF419575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSONTests" */; + buildConfigurationList = 2E4FEFF419575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON iOS Tests" */; buildPhases = ( 2E4FEFE219575BE100351305 /* Sources */, 2E4FEFE319575BE100351305 /* Frameworks */, @@ -192,87 +361,169 @@ dependencies = ( 2E4FEFE919575BE100351305 /* PBXTargetDependency */, ); - name = SwiftyJSONTests; + name = "SwiftyJSON iOS Tests"; productName = SwiftyJSONTests; - productReference = 2E4FEFE619575BE100351305 /* SwiftyJSONTests.xctest */; + productReference = 2E4FEFE619575BE100351305 /* SwiftyJSON iOS Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 2E4FF00119575CE600351305 /* SwiftyJSON-OSX */ = { + 7236B4EC1BAC14150020529B /* SwiftyJSON tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7236B4F31BAC14150020529B /* Build configuration list for PBXNativeTarget "SwiftyJSON tvOS" */; + buildPhases = ( + 7236B4F01BAC14150020529B /* Headers */, + 7236B4ED1BAC14150020529B /* Sources */, + 7236B4EF1BAC14150020529B /* Frameworks */, + 7236B4F21BAC14150020529B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SwiftyJSON tvOS"; + productName = SwiftyJSON; + productReference = 7236B4F61BAC14150020529B /* SwiftyJSON.framework */; + productType = "com.apple.product-type.framework"; + }; + 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON macOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 2E4FF01519575CE600351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON-OSX" */; + buildConfigurationList = 9C7DFC6E1A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS" */; buildPhases = ( - 2E4FEFFD19575CE600351305 /* Sources */, - 2E4FEFFE19575CE600351305 /* Frameworks */, - 2E4FEFFF19575CE600351305 /* Headers */, - 2E4FF00019575CE600351305 /* Resources */, + 9C7DFC581A9102BD005AA3F7 /* Headers */, + 9C7DFC561A9102BD005AA3F7 /* Sources */, + 9C7DFC571A9102BD005AA3F7 /* Frameworks */, + 9C7DFC591A9102BD005AA3F7 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = "SwiftyJSON-OSX"; - productName = "SwiftyJSON-OSX"; - productReference = 2E4FF00219575CE600351305 /* SwiftyJSON.framework */; + name = "SwiftyJSON macOS"; + productName = "SwiftyJSON OSX"; + productReference = 9C7DFC5B1A9102BD005AA3F7 /* SwiftyJSON.framework */; productType = "com.apple.product-type.framework"; }; - 2E4FF00B19575CE600351305 /* SwiftyJSON-OSXTests */ = { + 9C7DFC641A9102BD005AA3F7 /* SwiftyJSON macOS Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 2E4FF01819575CE600351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON-OSXTests" */; + buildConfigurationList = 9C7DFC711A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS Tests" */; buildPhases = ( - 2E4FF00819575CE600351305 /* Sources */, - 2E4FF00919575CE600351305 /* Frameworks */, - 2E4FF00A19575CE600351305 /* Resources */, + 9C7DFC611A9102BD005AA3F7 /* Sources */, + 9C7DFC621A9102BD005AA3F7 /* Frameworks */, + 9C7DFC631A9102BD005AA3F7 /* Resources */, ); buildRules = ( ); dependencies = ( - 2E4FF00F19575CE600351305 /* PBXTargetDependency */, + 9C7DFC681A9102BD005AA3F7 /* PBXTargetDependency */, ); - name = "SwiftyJSON-OSXTests"; - productName = "SwiftyJSON-OSXTests"; - productReference = 2E4FF00C19575CE600351305 /* SwiftyJSON-OSXTests.xctest */; + name = "SwiftyJSON macOS Tests"; + productName = "SwiftyJSON OSXTests"; + productReference = 9C7DFC651A9102BD005AA3F7 /* SwiftyJSON macOS Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + A8580F731BCF5C5B00DA927B /* SwiftyJSON tvOS Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = A8580F7C1BCF5C5B00DA927B /* Build configuration list for PBXNativeTarget "SwiftyJSON tvOS Tests" */; + buildPhases = ( + A8580F701BCF5C5B00DA927B /* Sources */, + A8580F711BCF5C5B00DA927B /* Frameworks */, + A8580F721BCF5C5B00DA927B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + A8580F7B1BCF5C5B00DA927B /* PBXTargetDependency */, + ); + name = "SwiftyJSON tvOS Tests"; + productName = "SwiftyJSON tvOS Tests"; + productReference = A8580F741BCF5C5B00DA927B /* SwiftyJSON tvOS Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + E4D7CCDE1B9465A700EE7221 /* SwiftyJSON watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = E4D7CCE51B9465A700EE7221 /* Build configuration list for PBXNativeTarget "SwiftyJSON watchOS" */; + buildPhases = ( + E4D7CCE21B9465A700EE7221 /* Headers */, + E4D7CCDF1B9465A700EE7221 /* Sources */, + E4D7CCE11B9465A700EE7221 /* Frameworks */, + E4D7CCE41B9465A700EE7221 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SwiftyJSON watchOS"; + productName = SwiftyJSON; + productReference = E4D7CCE81B9465A700EE7221 /* SwiftyJSON.framework */; + productType = "com.apple.product-type.framework"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 2E4FEFD219575BE100351305 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; + LastSwiftUpdateCheck = 0710; + LastUpgradeCheck = 1020; TargetAttributes = { 2E4FEFDA19575BE100351305 = { CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + ProvisioningStyle = Automatic; }; 2E4FEFE519575BE100351305 = { CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; + ProvisioningStyle = Manual; TestTargetID = 2E4FEFDA19575BE100351305; }; - 2E4FF00119575CE600351305 = { - CreatedOnToolsVersion = 6.0; + 7236B4EC1BAC14150020529B = { + LastSwiftMigration = 1000; + ProvisioningStyle = Automatic; }; - 2E4FF00B19575CE600351305 = { - CreatedOnToolsVersion = 6.0; - TestTargetID = 2E4FF00119575CE600351305; + 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 */; projectDirPath = ""; projectRoot = ""; targets = ( - 2E4FEFDA19575BE100351305 /* SwiftyJSON */, - 2E4FEFE519575BE100351305 /* SwiftyJSONTests */, - 2E4FF00119575CE600351305 /* SwiftyJSON-OSX */, - 2E4FF00B19575CE600351305 /* SwiftyJSON-OSXTests */, + 2E4FEFDA19575BE100351305 /* SwiftyJSON iOS */, + 2E4FEFE519575BE100351305 /* SwiftyJSON iOS Tests */, + 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON macOS */, + 9C7DFC641A9102BD005AA3F7 /* SwiftyJSON macOS Tests */, + E4D7CCDE1B9465A700EE7221 /* SwiftyJSON watchOS */, + 7236B4EC1BAC14150020529B /* SwiftyJSON tvOS */, + A8580F731BCF5C5B00DA927B /* SwiftyJSON tvOS Tests */, + A81D162B1E5743B000C62C5F /* SwiftLint */, ); }; /* End PBXProject section */ @@ -282,6 +533,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A1DE64C62BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -289,27 +541,68 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - A885D1DC19CFCFF0002FD4C3 /* SwiftyJSONTests.json in Resources */, + A885D1DC19CFCFF0002FD4C3 /* Tests.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7236B4F21BAC14150020529B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE64C92BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C7DFC591A9102BD005AA3F7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE64C72BC7D95C0097BCE6 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FF00019575CE600351305 /* Resources */ = { + 9C7DFC631A9102BD005AA3F7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9C459EF81A9103C1008C9A41 /* Tests.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FF00A19575CE600351305 /* Resources */ = { + A8580F721BCF5C5B00DA927B /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - A885D1DD19CFCFF0002FD4C3 /* SwiftyJSONTests.json in Resources */, + A81CBA0B1BCF6B0200A649A2 /* Tests.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E4D7CCE41B9465A700EE7221 /* Resources */ = { + 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; @@ -323,23 +616,95 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A885D1D219CF1EE6002FD4C3 /* SwiftyJSONTests.swift in Sources */, + 1B587CC61DDE04770012D8DB /* MergeTests.swift in Sources */, + A87080E819E439DA00CDE086 /* NumberTests.swift in Sources */, + A87080E419E3C2A600CDE086 /* SequenceTypeTests.swift in Sources */, + 5DD502911D9B21810004C112 /* NestedJSONTests.swift in Sources */, + 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 */, + A819C4A119E37FC600ADCC3D /* PrintableTests.swift in Sources */, + A819C49719E1A7DD00ADCC3D /* LiteralConvertibleTests.swift in Sources */, + A87080EA19E43C0700CDE086 /* StringTests.swift in Sources */, + A87080E619E3DF7800CDE086 /* ComparableTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7236B4ED1BAC14150020529B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7236B4EE1BAC14150020529B /* SwiftyJSON.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C7DFC561A9102BD005AA3F7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9C459EF51A910361008C9A41 /* SwiftyJSON.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C7DFC611A9102BD005AA3F7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1B587CC71DDE04780012D8DB /* MergeTests.swift in Sources */, + 9C459EFB1A9103C1008C9A41 /* SequenceTypeTests.swift in Sources */, + 9C459F001A9103C1008C9A41 /* ComparableTests.swift in Sources */, + 5DD502921D9B21810004C112 /* NestedJSONTests.swift in Sources */, + 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 */, + 9C459F011A9103C1008C9A41 /* StringTests.swift in Sources */, + 9C459F031A9103C1008C9A41 /* RawTests.swift in Sources */, + 9C459F051A9103C1008C9A41 /* ArrayTests.swift in Sources */, + 9C459EFD1A9103C1008C9A41 /* SubscriptTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FEFFD19575CE600351305 /* Sources */ = { + A8580F701BCF5C5B00DA927B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A885D1D519CF223F002FD4C3 /* SwiftyJSON.swift in Sources */, + 1B587CC81DDE04790012D8DB /* MergeTests.swift in Sources */, + A8580F801BCF69A000DA927B /* PerformanceTests.swift in Sources */, + A8580F811BCF69A000DA927B /* BaseTests.swift in Sources */, + 5DD502931D9B21810004C112 /* NestedJSONTests.swift in Sources */, + 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 */, + A8580F891BCF69A000DA927B /* NumberTests.swift in Sources */, + A8580F8A1BCF69A000DA927B /* RawTests.swift in Sources */, + A8580F8B1BCF69A000DA927B /* DictionaryTests.swift in Sources */, + A8580F8C1BCF69A000DA927B /* ArrayTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2E4FF00819575CE600351305 /* Sources */ = { + E4D7CCDF1B9465A700EE7221 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A885D1D319CF1EE6002FD4C3 /* SwiftyJSONTests.swift in Sources */, + E4D7CCE01B9465A700EE7221 /* SwiftyJSON.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -348,13 +713,18 @@ /* Begin PBXTargetDependency section */ 2E4FEFE919575BE100351305 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 2E4FEFDA19575BE100351305 /* SwiftyJSON */; + target = 2E4FEFDA19575BE100351305 /* SwiftyJSON iOS */; targetProxy = 2E4FEFE819575BE100351305 /* PBXContainerItemProxy */; }; - 2E4FF00F19575CE600351305 /* PBXTargetDependency */ = { + 9C7DFC681A9102BD005AA3F7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 2E4FF00119575CE600351305 /* SwiftyJSON-OSX */; - targetProxy = 2E4FF00E19575CE600351305 /* PBXContainerItemProxy */; + target = 9C7DFC5A1A9102BD005AA3F7 /* SwiftyJSON macOS */; + targetProxy = 9C7DFC671A9102BD005AA3F7 /* PBXContainerItemProxy */; + }; + A8580F7B1BCF5C5B00DA927B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7236B4EC1BAC14150020529B /* SwiftyJSON tvOS */; + targetProxy = A8580F7A1BCF5C5B00DA927B /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -363,26 +733,39 @@ 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; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = fast; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -394,11 +777,13 @@ 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; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -409,34 +794,50 @@ 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; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = YES; CURRENT_PROJECT_VERSION = 1; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = fast; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; 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; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -447,95 +848,178 @@ 2E4FEFF219575BE100351305 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + BITCODE_GENERATION_MODE = bitcode; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = SwiftyJSON/Info.plist; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = "Source/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = SwiftyJSON; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Debug; }; 2E4FEFF319575BE100351305 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + BITCODE_GENERATION_MODE = bitcode; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = SwiftyJSON/Info.plist; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = "Source/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = SwiftyJSON; SKIP_INSTALL = YES; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Release; }; 2E4FEFF519575BE100351305 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); + CODE_SIGN_IDENTITY = ""; + DEVELOPMENT_TEAM = ""; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = SwiftyJSONTests/Info.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_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; }; name = Debug; }; 2E4FEFF619575BE100351305 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = SwiftyJSONTests/Info.plist; + CODE_SIGN_IDENTITY = ""; + DEVELOPMENT_TEAM = ""; + 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_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 7236B4F41BAC14150020529B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + 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"; + 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; + }; + name = Debug; + }; + 7236B4F51BAC14150020529B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + 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"; + 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; }; name = Release; }; - 2E4FF01619575CE600351305 /* Debug */ = { + 9C7DFC6F1A9102BD005AA3F7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = SwiftyJSON/Info.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.9; - METAL_ENABLE_DEBUG_INFO = YES; - PRODUCT_MODULE_NAME = SwiftyJSON; - PRODUCT_NAME = SwiftyJSON; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + PLIST_FILE_OUTPUT_FORMAT = binary; + PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; - 2E4FF01719575CE600351305 /* Release */ = { + 9C7DFC701A9102BD005AA3F7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; @@ -543,54 +1027,169 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - INFOPLIST_FILE = SwiftyJSON/Info.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.9; - METAL_ENABLE_DEBUG_INFO = NO; - PRODUCT_MODULE_NAME = SwiftyJSON; - PRODUCT_NAME = SwiftyJSON; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PLIST_FILE_OUTPUT_FORMAT = binary; + PRODUCT_BUNDLE_IDENTIFIER = "com.swiftyjson.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Release; }; - 2E4FF01919575CE600351305 /* Debug */ = { + 9C7DFC721A9102BD005AA3F7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); + FRAMEWORK_SEARCH_PATHS = ""; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = SwiftyJSONTests/Info.plist; + INFOPLIST_FILE = "Tests/Info-macOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - METAL_ENABLE_DEBUG_INFO = YES; + 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; }; - 2E4FF01A19575CE600351305 /* Release */ = { + 9C7DFC731A9102BD005AA3F7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); - INFOPLIST_FILE = SwiftyJSONTests/Info.plist; + FRAMEWORK_SEARCH_PATHS = ""; + 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.9; - METAL_ENABLE_DEBUG_INFO = NO; + 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; + }; + A8580F7D1BCF5C5B00DA927B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_NO_COMMON_BLOCKS = YES; + 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; + }; + A8580F7E1BCF5C5B00DA927B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_NO_COMMON_BLOCKS = YES; + 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; + }; + E4D7CCE61B9465A700EE7221 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + BITCODE_GENERATION_MODE = bitcode; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + 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)"; + PRODUCT_NAME = SwiftyJSON; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "watchsimulator watchos"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 3.0; + }; + name = Debug; + }; + E4D7CCE71B9465A700EE7221 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + BITCODE_GENERATION_MODE = bitcode; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + 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)"; + PRODUCT_NAME = SwiftyJSON; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "watchsimulator watchos"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Release; }; @@ -606,7 +1205,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2E4FEFF119575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */ = { + 2E4FEFF119575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 2E4FEFF219575BE100351305 /* Debug */, @@ -615,7 +1214,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2E4FEFF419575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSONTests" */ = { + 2E4FEFF419575BE100351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON iOS Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 2E4FEFF519575BE100351305 /* Debug */, @@ -624,20 +1223,56 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2E4FF01519575CE600351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON-OSX" */ = { + 7236B4F31BAC14150020529B /* Build configuration list for PBXNativeTarget "SwiftyJSON tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7236B4F41BAC14150020529B /* Debug */, + 7236B4F51BAC14150020529B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9C7DFC6E1A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9C7DFC6F1A9102BD005AA3F7 /* Debug */, + 9C7DFC701A9102BD005AA3F7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9C7DFC711A9102BD005AA3F7 /* Build configuration list for PBXNativeTarget "SwiftyJSON macOS Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9C7DFC721A9102BD005AA3F7 /* Debug */, + 9C7DFC731A9102BD005AA3F7 /* Release */, + ); + 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 = ( - 2E4FF01619575CE600351305 /* Debug */, - 2E4FF01719575CE600351305 /* Release */, + A8580F7D1BCF5C5B00DA927B /* Debug */, + A8580F7E1BCF5C5B00DA927B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2E4FF01819575CE600351305 /* Build configuration list for PBXNativeTarget "SwiftyJSON-OSXTests" */ = { + E4D7CCE51B9465A700EE7221 /* Build configuration list for PBXNativeTarget "SwiftyJSON watchOS" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2E4FF01919575CE600351305 /* Debug */, - 2E4FF01A19575CE600351305 /* Release */, + E4D7CCE61B9465A700EE7221 /* Debug */, + E4D7CCE71B9465A700EE7221 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; 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 new file mode 100644 index 00000000..f4d10cb9 --- /dev/null +++ b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON iOS.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON macOS.xcscheme b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON macOS.xcscheme new file mode 100644 index 00000000..5ba84942 --- /dev/null +++ b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON macOS.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/SwiftyJSON.xcscheme b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme similarity index 56% rename from SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/SwiftyJSON.xcscheme rename to SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme index 8e41d518..c7c55338 100644 --- a/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/SwiftyJSON.xcscheme +++ b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON tvOS.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + + + + + + + diff --git a/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/SwiftyJSON-OSX.xcscheme b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON watchOS.xcscheme similarity index 62% rename from SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/SwiftyJSON-OSX.xcscheme rename to SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON watchOS.xcscheme index 3d8f288a..81445ecd 100644 --- a/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/SwiftyJSON-OSX.xcscheme +++ b/SwiftyJSON.xcodeproj/xcshareddata/xcschemes/SwiftyJSON watchOS.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + + + + + + + + + diff --git a/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/xcschememanagement.plist b/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index ef313fc5..00000000 --- a/SwiftyJSON.xcodeproj/xcuserdata/lebedzeu.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,42 +0,0 @@ - - - - - SchemeUserState - - SwiftyJSON-OSX.xcscheme - - orderHint - 1 - - SwiftyJSON.xcscheme - - orderHint - 0 - - - SuppressBuildableAutocreation - - 2E4FEFDA19575BE100351305 - - primary - - - 2E4FEFE519575BE100351305 - - primary - - - 2E4FF00119575CE600351305 - - primary - - - 2E4FF00B19575CE600351305 - - primary - - - - - diff --git a/SwiftyJSON.xcworkspace/contents.xcworkspacedata b/SwiftyJSON.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1ef2d2fa --- /dev/null +++ b/SwiftyJSON.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/SwiftyJSON.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftyJSON.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SwiftyJSON.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SwiftyJSON.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/SwiftyJSON.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..54782e32 --- /dev/null +++ b/SwiftyJSON.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/SwiftyJSON/SwiftyJSON.swift b/SwiftyJSON/SwiftyJSON.swift deleted file mode 100644 index caa25bc5..00000000 --- a/SwiftyJSON/SwiftyJSON.swift +++ /dev/null @@ -1,781 +0,0 @@ -// JSON.swift -// -// Copyright (c) 2014 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 - -@availability(*, unavailable, renamed="JSON") -public typealias JSONValue = JSON - -//MARK:- Base -//http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf -public enum JSON { - - //private type number - case ScalarNumber(NSNumber) - //private type string - case ScalarString(String) - //private type sequence - case Sequence(Array) - //private type mapping - case Mapping(Dictionary) - //private type null - case Null(NSError?) - - /** - :param: data The NSData used to convert to json. - :param: options The JSON serialization reading options. `.AllowFragments` by default. - :param: error The NSErrorPointer used to return the error. - */ - public init(data:NSData, options opt: NSJSONReadingOptions = .AllowFragments, error: NSErrorPointer = nil) { - if let object: AnyObject = NSJSONSerialization.JSONObjectWithData(data, options: opt, error: error){ - self = JSON(object: object) - } else { - self = .Null(nil) - } - } - - /** - :param: object The JSON object following the JSON's definition - */ - public init(object: AnyObject) { - switch object { - case let number as NSNumber: - self = .ScalarNumber(number) - case let string as NSString: - self = .ScalarString(string) - case let null as NSNull: - self = .Null(nil) - case let array as Array: - var jsonArray = Array() - for object : AnyObject in array { - let json = JSON(object: object) - if let error = json.error { - self = json - return - } else { - jsonArray.append(json) - } - } - self = .Sequence(jsonArray) - case let dictionary as Dictionary: - var jsonDictionary = Dictionary() - for (key : String, value : AnyObject) in dictionary { - let json = JSON(object: value) - if let error = json.error { - self = json - return - } else { - jsonDictionary[key] = json - } - } - self = .Mapping(jsonDictionary) - case let null as NSNull: - self = .Null(nil) - default: - self = .Null(NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"])) - } - } -} - -//MARK: - Return Error -//The SwiftyJSON's error domain -public let ErrorDomain: String! = "SwiftyJSONErrorDomain" -//The error code -public var ErrorUnsupportedType: Int { get { return 999 }} -public var ErrorIndexOutOfBounds: Int { get { return 900 }} -public var ErrorWrongType: Int { get { return 901 }} -public var ErrorNotExist: Int { get { return 500 }} - -extension JSON { - - // The error in the .Null enmu - public var error: NSError? { - get { - switch self { - case .Null(let error) where error != nil: - return error - default: - return nil; - } - } - } - -} - -//MARK:- Object -extension JSON { - - // The json object which is init(object:)'s parameter - public var object: AnyObject? { - switch self { - case .ScalarNumber(let number): - return number - case .ScalarString(let string): - return string - case .Null(let error) where error == nil: - return NSNull() - case .Sequence(let array): - var retArray = Array() - for json in array { - if let object: AnyObject = json.object { - retArray.append(object) - } - } - return retArray - case .Mapping(let dictionary): - var retDicitonary = Dictionary() - for (key : String, value : JSON) in dictionary { - if let object: AnyObject = value.object{ - retDicitonary[key] = object - } - } - return retDicitonary - default: - return nil - } - } -} - -// MARK: - Subscript -extension JSON { - - //if an array return the array[index]'s JSON else return .Null with error - public subscript(index: Int) -> JSON { - get { - switch self { - case .Sequence(let array): - if array.count > index { - return array[index] - } else { - return .Null(NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds , userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] is out of bounds"])) - } - default: - return .Null(NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Wrong type, It is not an array"])) - } - } - } - - //if an array return the dictionary[key]'s JSON else return .Null with error - public subscript(key: String) -> JSON { - get { - switch self { - case .Mapping(let dictionary): - if let value = dictionary[key] { - return value - } else { - return .Null(NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] does not exist"])) - } - default: - return .Null(NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Wrong type, It is not an dictionary"])) - } - } - } -} - -//MARK: - Printable, DebugPrintable -extension JSON: Printable, DebugPrintable { - - public var description: String { - switch self { - case .ScalarNumber(let number): - if number.isBool { - return number.boolValue.description - } else { - return number.description - } - case .ScalarString(let string): - return string - case .Sequence(let array): - return array.description - case .Mapping(let dictionary): - return dictionary.description - case .Null(let error) where error != nil : - return error!.description - default: - return "null" - } - } - - public var debugDescription: String { - get { - switch self { - case .ScalarNumber(let number): - if number.isBool { - return number.boolValue.description - } else { - return number.debugDescription - } - case .ScalarString(let string): - return string.debugDescription - case .Sequence(let array): - return array.debugDescription - case .Mapping(let dictionary): - return dictionary.debugDescription - case .Null(let error) where error != nil : - return error!.debugDescription - default: - return "null" - } - } - } -} - -// MARK: - Sequence: Array -extension JSON { - - //Optional array - public var array: Array? { - get { - switch self { - case .Sequence(let array): - return array - default: - return nil - } - } - } - - //Non-optional array - public var arrayValue: Array { - get { - return self.array ?? [] - } - } -} - -// MARK: - Mapping: Dictionary -extension JSON { - - //Optional dictionary - public var dictionary: Dictionary? { - get { - switch self { - case .Mapping(let dictionary): - return dictionary - default: - return nil - } - } - } - - //Non-optional dictionary - public var dictionaryValue: Dictionary { - get { - return self.dictionary ?? [:] - } - } -} - -//MARK: - Scalar: Bool -extension JSON: BooleanType { - - //Optional bool - public var bool: Bool? { - get { - switch self { - case .ScalarNumber(let number) where number.isBool: - return number.boolValue - default: - return nil - } - } - } - - //Non-optional bool - public var boolValue: Bool { - switch self { - case .ScalarNumber(let number): - return number.boolValue - case .ScalarString(let string): - return (string as NSString).boolValue - case .Sequence(let array): - return array.count > 0 - case .Mapping(let dictionary): - return dictionary.count > 0 - case .Null: - return false - default: - return true - } - } -} - -//MARK: - Scalar: String -extension JSON { - - //Optional string - public var string: String? { - get { - switch self { - case .ScalarString(let string): - return string - default: - return nil - } - } - } - - //Non-optional string - public var stringValue: String { - get { - switch self { - case .ScalarString(let string): - return string - case .ScalarNumber(let number): - if number.isBool { - return number.boolValue.description - } else { - return number.stringValue - } - default: - return "" - } - } - } -} - -//MARK: - Scalar: Number -extension JSON { - - //Optional number - public var number: NSNumber? { - get { - switch self { - case .ScalarNumber(let number): - return number - default: - return nil - } - } - } - - //Non-optional number - public var numberValue: NSNumber { - get { - switch self { - case .ScalarString(let string): - let scanner = NSScanner(string: string) - if scanner.scanDouble(nil){ - if (scanner.atEnd) { - return NSNumber(double:(string as NSString).doubleValue) - } - } - return NSNumber(double: 0.0) - case .ScalarNumber(let number): - return number - default: - return NSNumber(double: 0.0) - } - } - } -} - -//MARK: - Null -extension JSON { - - public var null: NSNull? { - get { - switch self { - case .Null(let error) where error == nil: - return NSNull() - default: - return nil - } - } - } -} - -//MARK: - URL -extension JSON { - - //Optional URL - public var URL: NSURL? { - get { - switch self { - case .ScalarString(let string): - if let encodedString = string.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) { - return NSURL(string: encodedString) - } else { - return nil - } - default: - return nil - } - } - } -} - -//MARK: - Int, Double, Float, Int8, Int16, Int32, Int64 -extension JSON { - - //Optional Int8 - public var char: Int8? { - get { - return self.number?.charValue - } - } - - //Optional Int8 - public var charValue: Int8 { - get { - return self.numberValue.charValue - } - } - - //Optional UInt8 - public var unsignedChar: UInt8? { - get{ - return self.number?.unsignedCharValue - } - } - - //Non-optional UInt8 - public var unsignedCharValue: UInt8 { - get{ - return self.numberValue.unsignedCharValue - } - } - - //Optional Int16 - public var short: Int16? { - get{ - return self.number?.shortValue - } - } - - //Non-optional UInt8 - public var shortValue: Int16 { - get{ - return self.numberValue.shortValue - } - } - - //Optional UInt16 - public var unsignedShort: UInt16? { - get{ - return self.number?.unsignedShortValue - } - } - - //Non-optional UInt16 - public var unsignedShortValue: UInt16 { - get{ - return self.numberValue.unsignedShortValue - } - } - - //Optional Int - public var long: Int? { - get{ - return self.number?.longValue - } - } - - //Non-optional Int - public var longValue: Int { - get{ - return self.numberValue.longValue - } - } - - //Optional UInt - public var unsignedLong: UInt? { - get{ - return self.number?.unsignedLongValue - } - } - - //Non-optional UInt - public var unsignedLongValue: UInt { - get{ - return self.numberValue.unsignedLongValue - } - } - - //Optional Int64 - public var longLong: Int64? { - get{ - return self.number?.longLongValue - } - } - - //Non-optional Int64 - public var longLongValue: Int64 { - get{ - return self.numberValue.longLongValue - } - } - - //Optional UInt64 - public var unsignedLongLong: UInt64? { - get{ - return self.number?.unsignedLongLongValue - } - } - - //Non-optional UInt64 - public var unsignedLongLongValue: UInt64 { - get{ - return self.numberValue.unsignedLongLongValue - } - } - - //Optional Float - public var float: Float? { - get { - return self.number?.floatValue - } - } - - //Non-optional Float - public var floatValue: Float { - get { - return self.numberValue.floatValue - } - } - - //Optional Double - public var double: Double? { - get { - return self.number?.doubleValue - } - } - - //Non-optional Double - public var doubleValue: Double { - get { - return self.numberValue.doubleValue - } - } - - //Optional Int - public var integer: Int? { - get { - return self.number?.integerValue - } - } - - //Non-optional Int - public var integerValue: Int { - get { - return self.numberValue.integerValue - } - } - - //Optional Int - public var unsignedInteger: Int? { - get { - return self.number?.unsignedIntegerValue - } - } - - //Non-optional Int - public var unsignedIntegerValue: Int { - get { - return self.numberValue.unsignedIntegerValue - } - } - - //Optional Int32 - public var int: Int32? { - get { - return self.number?.intValue - } - } - - //non-optional Int32 - public var intValue: Int32 { - get { - return self.numberValue.intValue - } - } -} - -//MARK: - Comparable -extension JSON: Comparable {} - -public func ==(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs, rhs) { - case (.ScalarNumber(let l), .ScalarNumber(let r)): - return l == r - case (.ScalarString(let l), .ScalarString(let r)): - return l == r - case (.Sequence(let l), .Sequence(let r)): - return l == r - case (.Mapping(let l), .Mapping(let r)): - return l == r - case (.Mapping(let l), .Mapping(let r)): - return l == r - case (.Null(let l), .Null(let r)): - let lcode = l?.code ?? 0 - let rcode = l?.code ?? 0 - return lcode == rcode - default: - return false - } -} - -public func !=(lhs: JSON, rhs: JSON) -> Bool { - return !(lhs == rhs) -} - -public func <=(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs, rhs) { - case (.ScalarNumber(let l), .ScalarNumber(let r)): - return l <= r - case (.ScalarString(let l), .ScalarString(let r)): - return l <= r - case (.Sequence(let l), .Sequence(let r)): - return l == r - case (.Mapping(let l), .Mapping(let r)): - return l == r - case (.Null(let l), .Null(let r)): - let lcode = l?.code ?? 0 - let rcode = l?.code ?? 0 - return lcode == rcode - default: - return false - } -} - -public func >=(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs, rhs) { - case (.ScalarNumber(let l), .ScalarNumber(let r)): - return l >= r - case (.ScalarString(let l), .ScalarString(let r)): - return l >= r - case (.Sequence(let l), .Sequence(let r)): - return l == r - case (.Mapping(let l), .Mapping(let r)): - return l == r - case (.Null(let l), .Null(let r)): - let lcode = l?.code ?? 0 - let rcode = l?.code ?? 0 - return lcode == rcode - default: - return false - } -} - -public func >(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs, rhs) { - case (.ScalarNumber(let l), .ScalarNumber(let r)): - return l > r - case (.ScalarString(let l), .ScalarString(let r)): - return l > r - default: - return false - } -} - -public func <(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs, rhs) { - case (.ScalarNumber(let l), .ScalarNumber(let r)): - return l < r - case (.ScalarString(let l), .ScalarString(let r)): - return l < r - default: - return false - } -} - -// MARK: - NSNumber: Comparable -extension NSNumber: Comparable { - var isBool:Bool { - get { - switch String.fromCString(self.objCType)! { - case "c", "C": - return true - default: - return false - } - } - } -} - -public 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) == NSComparisonResult.OrderedSame - } -} - -public func !=(lhs: NSNumber, rhs: NSNumber) -> Bool { - return !(rhs == rhs) -} - -public 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) == NSComparisonResult.OrderedAscending - } -} - -public 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) == NSComparisonResult.OrderedDescending - } -} - -public 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) != NSComparisonResult.OrderedDescending - } -} - -public 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) != NSComparisonResult.OrderedAscending - } -} \ No newline at end of file diff --git a/SwiftyJSONTests/SwiftyJSONTests.swift b/SwiftyJSONTests/SwiftyJSONTests.swift deleted file mode 100644 index d1b01ad1..00000000 --- a/SwiftyJSONTests/SwiftyJSONTests.swift +++ /dev/null @@ -1,278 +0,0 @@ -// SwiftyJSONTests.swift -// -// Copyright (c) 2014 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 UIKit -import XCTest -import SwiftyJSON - -class SwiftyJSONTests: XCTestCase { - - var testData: NSData! - - override func setUp() { - - super.setUp() - - if let file = NSBundle(forClass:SwiftyJSONTests.self).pathForResource("SwiftyJSONTests", ofType: "json") { - self.testData = NSData(contentsOfFile: file) - } else { - XCTFail("Can't find the test JSON file") - } - } - - override func tearDown() { - super.tearDown() - } - - func testInit() { - let json0 = JSON(data:self.testData) - XCTAssertEqual(json0.array!.count, 3) - XCTAssertEqual(JSON(object: "123").description, "123") - XCTAssertEqual(JSON(object: ["1":"2"]).description, ["1":"2"].description) - var dictionary = NSMutableDictionary() - dictionary.setObject(NSNumber(double: 1.0), forKey: "number" as NSString) - dictionary.setObject(NSNull(), forKey: "null" as NSString) - let json1 = JSON(object: dictionary) - if let object: AnyObject = NSJSONSerialization.JSONObjectWithData(self.testData, options: nil, error: nil){ - let json2 = JSON(object: object) - XCTAssertEqual(json0, json2) - } - } - - func testCompare() { - XCTAssertNotEqual(JSON(object: "32.1234567890"), JSON(object: 32.1234567890)) - XCTAssertNotEqual(JSON(object: "9876543210987654321"),JSON(object: NSNumber(unsignedLongLong:9876543210987654321))) - XCTAssertNotEqual(JSON(object: "9876543210987654321.12345678901234567890"), JSON(object: 9876543210987654321.12345678901234567890)) - XCTAssertEqual(JSON(object: "😊"), JSON(object: "😊")) - XCTAssertNotEqual(JSON(object: "😱"), JSON(object: "😁")) - XCTAssertEqual(JSON(object: [123,321,456]), JSON(object: [123,321,456])) - XCTAssertNotEqual(JSON(object: [123,321,456]), JSON(object: 123456789)) - XCTAssertNotEqual(JSON(object: [123,321,456]), JSON(object: "string")) - XCTAssertNotEqual(JSON(object: ["1":123,"2":321,"3":456]), JSON(object: "string")) - XCTAssertEqual(JSON(object: ["1":123,"2":321,"3":456]), JSON(object: ["2":321,"1":123,"3":456])) - XCTAssertEqual(JSON(object: NSNull()),JSON(object: NSNull())) - XCTAssertNotEqual(JSON(object: NSNull()), JSON(object: 123)) - } - - func testJSONDoesProduceValidWithCorrectKeyPath() { - let json = JSON(data:self.testData) - - let tweets = json - let tweets_array = json.array - let tweets_1 = json[1] - let tweets_array_1 = tweets_1[1] - let tweets_1_user_name = tweets_1["user"]["name"] - let tweets_1_user_name_string = tweets_1["user"]["name"].string - XCTAssertNotEqual(tweets, JSON.Null(nil)) - XCTAssert(tweets_array != nil) - XCTAssertNotEqual(tweets_1, JSON.Null(nil)) - XCTAssertEqual(tweets_1_user_name, JSON(object:"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(object:[-122.25831,37.871609]) - XCTAssertEqual(tweets_1_coordinates_coordinates, new_tweets_1_coordinates_coordinates) - XCTAssertEqual(tweets_1_coordinates_coordinates_point_0_double!, -122.25831) - XCTAssertEqual(tweets_1_coordinates_coordinates_point_1_float!, 37.871609) - let tweets_1_coordinates_coordinates_point_0_string = tweets_1_coordinates_coordinates[0].stringValue - let tweets_1_coordinates_coordinates_point_1_string = tweets_1_coordinates_coordinates[1].stringValue - XCTAssertEqual(tweets_1_coordinates_coordinates_point_0_string, "-122.25831") - XCTAssertEqual(tweets_1_coordinates_coordinates_point_1_string, "37.871609") - let tweets_1_coordinates_coordinates_point_0 = tweets_1_coordinates_coordinates[0] - let tweets_1_coordinates_coordinates_point_1 = tweets_1_coordinates_coordinates[1] - XCTAssertEqual(tweets_1_coordinates_coordinates_point_0, JSON(object:-122.25831)) - XCTAssertEqual(tweets_1_coordinates_coordinates_point_1, JSON(object: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"].longLong - 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") - XCTAssertFalse(favorited!) - XCTAssertEqual(id!,240558470661799936) - XCTAssertEqual(in_reply_to_user_id_str,JSON.Null(nil)) - - let user = json[0]["user"] - let user_name = user["name"].string - let user_profile_image_url = user["profile_image_url"].URL - XCTAssert(user_name == "OAuth Dancer") - XCTAssert(user_profile_image_url == NSURL(string: "http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg")) - - let user_dictionary = json[0]["user"].dictionary - let user_dictionary_name = user_dictionary?["name"]?.string - let user_dictionary_name_profile_image_url = user_dictionary?["profile_image_url"]?.URL - XCTAssert(user_dictionary_name == "OAuth Dancer") - XCTAssert(user_dictionary_name_profile_image_url == NSURL(string: "http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg")) - } - - func testJSONNumberCompare() { - XCTAssertEqual(JSON(object: 12376352.123321), JSON(object: 12376352.123321)) - XCTAssertGreaterThan(JSON(object: 20.211), JSON(object: 20.112)) - XCTAssertGreaterThanOrEqual(JSON(object: 30.211), JSON(object: 20.112)) - XCTAssertGreaterThanOrEqual(JSON(object: 65232), JSON(object: 65232)) - XCTAssertLessThan(JSON(object: -82320.211), JSON(object: 20.112)) - XCTAssertLessThanOrEqual(JSON(object: -320.211), JSON(object: 123.1)) - XCTAssertLessThanOrEqual(JSON(object: -8763), JSON(object: -8763)) - - XCTAssertEqual(JSON(object: 12376352.123321), JSON(object: 12376352.123321)) - XCTAssertGreaterThan(JSON(object: 20.211), JSON(object: 20.112)) - XCTAssertGreaterThanOrEqual(JSON(object: 30.211), JSON(object: 20.112)) - XCTAssertGreaterThanOrEqual(JSON(object: 65232), JSON(object: 65232)) - XCTAssertLessThan(JSON(object: -82320.211), JSON(object: 20.112)) - XCTAssertLessThanOrEqual(JSON(object: -320.211), JSON(object: 123.1)) - XCTAssertLessThanOrEqual(JSON(object: -8763), JSON(object: -8763)) - } - - func testNumberConverToString(){ - XCTAssertEqual(JSON(object: true).stringValue, "true") - XCTAssertEqual(JSON(object: 999.9823).stringValue, "999.9823") - - XCTAssertEqual(JSON(object: true).number!.stringValue, "1") - XCTAssertEqual(JSON(object: false).number!.stringValue, "0") - XCTAssertEqual(JSON(object: "hello").numberValue.stringValue, "0") - XCTAssertEqual(JSON(object: NSNull()).numberValue.stringValue, "0") - XCTAssertEqual(JSON(object: ["a","b","c","d"]).numberValue.stringValue, "0") - XCTAssertEqual(JSON(object: ["a":"b","c":"d"]).numberValue.stringValue, "0") - } - - func testNumberPrint(){ - - XCTAssertEqual(JSON(object: false).description,"false") - XCTAssertEqual(JSON(object: true).description,"true") - - XCTAssertEqual(JSON(object: 1).description,"1") - XCTAssertEqual(JSON(object: 22).description,"22") - XCTAssertEqual(JSON(object: 2147483647).description,"2147483647") - XCTAssertEqual(JSON(object: 2147483648).description,"2147483648") - - XCTAssertEqual(JSON(object: -1).description,"-1") - XCTAssertEqual(JSON(object: -934834834).description,"-934834834") - XCTAssertEqual(JSON(object: -2147483648).description,"-2147483648") - - XCTAssertEqual(JSON(object: 1.5555).description,"1.5555") - XCTAssertEqual(JSON(object: -9.123456789).description,"-9.123456789") - XCTAssertEqual(JSON(object: -0.00000000000000001).description,"-1e-17") - XCTAssertEqual(JSON(object: -999999999999999999999999.000000000000000000000001).description,"-1e+24") - XCTAssertEqual(JSON(object: -9999999991999999999999999.88888883433343439438493483483943948341).stringValue,"-9.999999991999999e+24") - - XCTAssertEqual(JSON(object: Int(Int.max)).description,"\(Int.max)") - XCTAssertEqual(JSON(object: NSNumber(long: Int.min)).description,"\(Int.min)") - XCTAssertEqual(JSON(object: NSNumber(unsignedLong: ULONG_MAX)).description,"\(ULONG_MAX)") - XCTAssertEqual(JSON(object: NSNumber(unsignedLongLong: UInt64.max)).description,"\(UInt64.max)") - XCTAssertEqual(JSON(object: NSNumber(longLong: Int64.max)).description,"\(Int64.max)") - XCTAssertEqual(JSON(object: NSNumber(unsignedLongLong: UInt64.max)).description,"\(UInt64.max)") - - XCTAssertEqual(JSON(object: Double.infinity).description,"inf") - XCTAssertEqual(JSON(object: -Double.infinity).description,"-inf") - XCTAssertEqual(JSON(object: Double.NaN).description,"nan") - - XCTAssertEqual(JSON(object: 1.0/0.0).description,"inf") - XCTAssertEqual(JSON(object: -1.0/0.0).description,"-inf") - XCTAssertEqual(JSON(object: 0.0/0.0).description,"nan") - } - - func testNullPrint() { - XCTAssertEqual(JSON.Null(nil).debugDescription,"null") - let error = NSError(domain: SwiftyJSON.ErrorDomain, code: SwiftyJSON.ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "hello world"]) - XCTAssertEqual(JSON.Null(error).description,"\(error)") - } - - func testErrorHandle() { - let json = JSON(data:self.testData) - if let wrongType = json["wrong-type"].string { - XCTFail("Should not run into here") - } else { - XCTAssertEqual(json["wrong-type"].error!.code, SwiftyJSON.ErrorWrongType) - } - - if let notExist = json[0]["not-exist"].string { - XCTFail("Should not run into here") - } else { - XCTAssertEqual(json[0]["not-exist"].error!.code, SwiftyJSON.ErrorNotExist) - } - - let wrongJSON = JSON(object: NSObject()) - if let error = wrongJSON.error { - XCTAssertEqual(error.code, SwiftyJSON.ErrorUnsupportedType) - } - } - - func testReturnObject() { - let json = JSON(data:self.testData) - println(json.object) - XCTAssertNotNil(json.object) - } - - func testJSONURLPercentEscapes() { - let emDash = "\\u2014" - let urlString = "http://examble.com/unencoded" + emDash + "string" - let encodedURLString = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) - - let json = JSON(object: urlString) - XCTAssertEqual(json.URL!, NSURL(string: encodedURLString!), "Wrong unpacked ") - } - - func testNumberCompare(){ - XCTAssertEqual(NSNumber(double: 888332), NSNumber(int:888332)) - XCTAssertNotEqual(NSNumber(double: 888332.1), NSNumber(int:888332)) - XCTAssertLessThan(NSNumber(int: 888332), NSNumber(double:888332.1)) - XCTAssertGreaterThan(NSNumber(double: 888332.1), NSNumber(int:888332)) - XCTAssertNotEqual(NSNumber(double: 1), NSNumber(bool:true)) - XCTAssertNotEqual(NSNumber(int: 0), NSNumber(bool:false)) - XCTAssertEqual(NSNumber(bool: false), NSNumber(bool:false)) - XCTAssertEqual(NSNumber(bool: true), NSNumber(bool:true)) - } - - func testInitPerformance() { - - self.measureBlock() { - var t:Int = 0 - while (true) { - if t == 100 { - break - } - JSON(data:self.testData) - t++ - } - } - } - - func testObjectMethodPerformance() { - var json = JSON(data:self.testData) - self.measureBlock() { - var t:Int = 0 - while (true) { - if t == 100 { - break - } - json.object - t++ - } - } - } - -} \ No newline at end of file diff --git a/SwiftyJSONTests/Info.plist b/Tests/Info-iOS.plist similarity index 91% rename from SwiftyJSONTests/Info.plist rename to Tests/Info-iOS.plist index fe602613..6d32c15c 100644 --- a/SwiftyJSONTests/Info.plist +++ b/Tests/Info-iOS.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - SwiftJSON.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Tests/Info-macOS.plist b/Tests/Info-macOS.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/Tests/Info-macOS.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Tests/Info-tvOS.plist b/Tests/Info-tvOS.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/Tests/Info-tvOS.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Tests/SwiftJSONTests/ArrayTests.swift b/Tests/SwiftJSONTests/ArrayTests.swift new file mode 100644 index 00000000..0c955e7d --- /dev/null +++ b/Tests/SwiftJSONTests/ArrayTests.swift @@ -0,0 +1,45 @@ +// ArrayTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class ArrayTests: XCTestCase { + + func testSingleDimensionalArraysGetter() { + 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") + XCTAssertEqual((json.array![2] as JSON).string!, "a") + 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"] + var json = JSON(array) + json.arrayObject = ["111", "222"] + XCTAssertEqual((json.array![0] as JSON).string!, "111") + XCTAssertEqual((json.array![1] as JSON).string!, "222") + } +} diff --git a/Tests/SwiftJSONTests/BaseTests.swift b/Tests/SwiftJSONTests/BaseTests.swift new file mode 100644 index 00000000..8bbebcde --- /dev/null +++ b/Tests/SwiftJSONTests/BaseTests.swift @@ -0,0 +1,280 @@ +// BaseTests.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 + +class BaseTests: XCTestCase { + + var testData: Data! + + override func setUp() { + + super.setUp() + + #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() { + 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") + let dictionary = NSMutableDictionary() + dictionary.setObject(NSNumber(value: 1.0), forKey: "number" as NSString) + dictionary.setObject(NSNull(), forKey: "null" as NSString) + _ = JSON(dictionary) + do { + let object: Any = try JSONSerialization.jsonObject(with: self.testData, options: []) + let json2 = JSON(object) + XCTAssertEqual(json0, json2) + } catch _ { + } + } + + func testCompare() { + XCTAssertNotEqual(JSON("32.1234567890"), JSON(32.1234567890)) + 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())) + XCTAssertNotEqual(JSON(NSNull()), JSON(123)) + } + + func testJSONDoesProduceValidWithCorrectKeyPath() { + + 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] + _ = tweets_1[1] + let tweets_1_user_name = tweets_1["user"]["name"] + let tweets_1_user_name_string = tweets_1["user"]["name"].string + XCTAssertNotEqual(tweets.type, Type.null) + XCTAssert(tweets_array != nil) + 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) + 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) + let tweets_1_coordinates_coordinates_point_0_string = tweets_1_coordinates_coordinates[0].stringValue + let tweets_1_coordinates_coordinates_point_1_string = tweets_1_coordinates_coordinates[1].stringValue + XCTAssertEqual(tweets_1_coordinates_coordinates_point_0_string, "-122.25831") + XCTAssertEqual(tweets_1_coordinates_coordinates_point_1_string, "37.871609") + let tweets_1_coordinates_coordinates_point_0 = tweets_1_coordinates_coordinates[0] + 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") + XCTAssertFalse(favorited!) + XCTAssertEqual(id!, 240558470661799936) + XCTAssertEqual(in_reply_to_user_id_str.type, Type.null) + + let user = json[0]["user"] + let user_name = user["name"].string + let user_profile_image_url = user["profile_image_url"].url + XCTAssert(user_name == "OAuth Dancer") + XCTAssert(user_profile_image_url == URL(string: "http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg")) + + let user_dictionary = json[0]["user"].dictionary + let user_dictionary_name = user_dictionary?["name"]?.string + let user_dictionary_name_profile_image_url = user_dictionary?["profile_image_url"]?.url + 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)) + XCTAssertGreaterThanOrEqual(JSON(30.211), JSON(20.112)) + XCTAssertGreaterThanOrEqual(JSON(65232), JSON(65232)) + 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)) + XCTAssertGreaterThanOrEqual(JSON(65232), JSON(65232)) + XCTAssertLessThan(JSON(-82320.211), JSON(20.112)) + XCTAssertLessThanOrEqual(JSON(-320.211), JSON(123.1)) + XCTAssertLessThanOrEqual(JSON(-8763), JSON(-8763)) + } + + 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") + } + + func testNumberPrint() { + + XCTAssertEqual(JSON(false).description, "false") + XCTAssertEqual(JSON(true).description, "true") + + XCTAssertEqual(JSON(1).description, "1") + XCTAssertEqual(JSON(22).description, "22") + #if (arch(x86_64) || arch(arm64)) + XCTAssertEqual(JSON(9.22337203685478E18).description, "9.22337203685478e+18") + #elseif (arch(i386) || arch(arm)) + 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") + } + + func testNullJSON() { + XCTAssertEqual(JSON(NSNull()).debugDescription, "null") + + let json: JSON = JSON.null + XCTAssertEqual(json.debugDescription, "null") + XCTAssertNil(json.error) + let json1: JSON = JSON(NSNull()) + if json1 != JSON.null { + XCTFail("json1 should be nil") + } + } + + func testExistance() { + 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 jsonForArray = JSON(array) + XCTAssertTrue(jsonForArray[0].exists()) + XCTAssertFalse(jsonForArray[1].exists()) + XCTAssertFalse(jsonForArray["someValue"].exists()) + } + + func testErrorHandle() { + 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, SwiftyJSONError.wrongType) + } + + if json[0]["not-exist"].string != nil { + XCTFail("Should not run into here") + } else { + XCTAssertEqual(json[0]["not-exist"].error, SwiftyJSONError.notExist) + } + + let wrongJSON = JSON(NSObject()) + if let error = wrongJSON.error { + XCTAssertEqual(error, SwiftyJSONError.unsupportedType) + } + } + + func testReturnObject() { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + XCTAssertNotNil(json.object) + } + + 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/SwiftJSONTests/ComparableTests.swift b/Tests/SwiftJSONTests/ComparableTests.swift new file mode 100644 index 00000000..a7b69086 --- /dev/null +++ b/Tests/SwiftJSONTests/ComparableTests.swift @@ -0,0 +1,337 @@ +// ComparableTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class ComparableTests: XCTestCase { + + func testNumberEqual() { + 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) + XCTAssertEqual(jsonL2, jsonR2) + XCTAssertTrue(jsonR2 == 987654321) + + 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) + XCTAssertNotEqual(jsonL1, jsonR1) + XCTAssertFalse(jsonL1 == 34343) + + 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)) + XCTAssertNotEqual(jsonL3, jsonR3) + XCTAssertFalse(jsonL3 == 4545.232) + } + + func testNumberGreaterThanOrEqual() { + 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) + XCTAssertGreaterThanOrEqual(jsonL2, jsonR2) + XCTAssertTrue(jsonR2 >= -988343) + + 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) + XCTAssertLessThanOrEqual(jsonR1, jsonL1) + XCTAssertFalse(83487343.3493 <= jsonR1) + + 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)) + XCTAssertLessThanOrEqual(jsonR3, jsonL3) + XCTAssertTrue(87621.12345678 <= jsonR3) + } + + func testNumberGreaterThan() { + 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) + XCTAssertGreaterThan(jsonL2, jsonR2) + XCTAssertFalse(jsonR2 > 877434) + + 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) + XCTAssertLessThan(jsonR1, jsonL1) + XCTAssertTrue(jsonR1 < 192388843.0988) + + 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)) + XCTAssertLessThan(jsonR3, jsonL3) + XCTAssertTrue(-7799 < jsonR3) + } + + func testBoolEqual() { + let jsonL1: JSON = true + let jsonR1: JSON = JSON(true) + XCTAssertEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 == true) + + 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) + XCTAssertNotEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 != false) + + 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) + XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 >= true) + + 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) + XCTAssertLessThanOrEqual(jsonL1, jsonR1) + XCTAssertTrue(true <= jsonR1) + + 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) + XCTAssertFalse(jsonL1 > jsonR1) + XCTAssertFalse(jsonL1 > true) + XCTAssertFalse(jsonR1 > 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) + XCTAssertFalse(jsonL3 > jsonR3) + XCTAssertFalse(jsonL3 > false) + XCTAssertFalse(jsonR3 > 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) + XCTAssertFalse(jsonL1 < jsonR1) + XCTAssertFalse(jsonL1 < true) + XCTAssertFalse(jsonR1 < 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) + XCTAssertFalse(jsonL3 < jsonR3) + XCTAssertFalse(jsonL3 < false) + XCTAssertFalse(jsonR3 < 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 !@#$%^&*()") + + XCTAssertEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 == "abcdefg 123456789 !@#$%^&*()") + } + + func testStringNotEqual() { + 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 !@#$%^&*()") + + XCTAssertGreaterThanOrEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 >= "abcdefg 123456789 !@#$%^&*()") + + 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 !@#$%^&*()") + + XCTAssertLessThanOrEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 <= "abcdefg 123456789 !@#$%^&*()") + + 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 !@#$%^&*()") + + XCTAssertFalse(jsonL1 > jsonR1) + XCTAssertFalse(jsonL1 > "abcdefg 123456789 !@#$%^&*()") + + 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 !@#$%^&*()") + + XCTAssertFalse(jsonL1 < jsonR1) + XCTAssertFalse(jsonL1 < "abcdefg 123456789 !@#$%^&*()") + + 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()) + XCTAssertEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 != "123") + XCTAssertFalse(jsonL1 > "abcd") + XCTAssertFalse(jsonR1 < "*&^") + XCTAssertFalse(jsonL1 >= "jhfid") + XCTAssertFalse(jsonR1 <= "你好") + 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"]) + XCTAssertEqual(jsonL1, jsonR1) + XCTAssertTrue(jsonL1 == [1, 2, "4", 5, "6"]) + XCTAssertTrue(jsonL1 != ["abcd", "efg"]) + XCTAssertTrue(jsonL1 >= jsonR1) + XCTAssertTrue(jsonL1 <= jsonR1) + 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()]]) + + XCTAssertEqual(jsonL1, jsonR1) + 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"]) + } +} 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/SwiftJSONTests/DictionaryTests.swift b/Tests/SwiftJSONTests/DictionaryTests.swift new file mode 100644 index 00000000..dc89200e --- /dev/null +++ b/Tests/SwiftJSONTests/DictionaryTests.swift @@ -0,0 +1,55 @@ +// DictionaryTests.swift +// +// Copyright (c) 2014 - 2017 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 + +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 json = JSON(dictionary) + //dictionary + XCTAssertEqual((json.dictionary!["number"]! as JSON).double!, 9823.212) + XCTAssertEqual((json.dictionary!["name"]! as JSON).string!, "NAME") + XCTAssertEqual(((json.dictionary!["list"]! as JSON).array![0] as JSON).int!, 1234) + XCTAssertEqual(((json.dictionary!["list"]! as JSON).array![1] as JSON).double!, 4.212) + XCTAssertEqual((((json.dictionary!["object"]! as JSON).dictionaryValue)["sub_number"]! as JSON).double!, 877.2323) + XCTAssertTrue(json.dictionary!["null"] == nil) + //dictionaryValue + XCTAssertEqual(((((json.dictionaryValue)["object"]! as JSON).dictionaryValue)["sub_name"]! as JSON).string!, "sub_name") + XCTAssertEqual((json.dictionaryValue["bool"]! as JSON).bool!, true) + XCTAssertTrue(json.dictionaryValue["null"] == nil) + XCTAssertTrue(JSON.null.dictionaryValue == [:]) + //dictionaryObject + XCTAssertEqual(json.dictionaryObject!["number"]! as? Double, 9823.212) + 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"]) + } +} diff --git a/Tests/SwiftJSONTests/LiteralConvertibleTests.swift b/Tests/SwiftJSONTests/LiteralConvertibleTests.swift new file mode 100644 index 00000000..9e478c7b --- /dev/null +++ b/Tests/SwiftJSONTests/LiteralConvertibleTests.swift @@ -0,0 +1,73 @@ +// LiteralConvertibleTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class LiteralConvertibleTests: XCTestCase { + + func testNumber() { + var json: JSON = 1234567890.876623 + XCTAssertEqual(json.int!, 1234567890) + XCTAssertEqual(json.intValue, 1234567890) + XCTAssertEqual(json.double!, 1234567890.876623) + XCTAssertEqual(json.doubleValue, 1234567890.876623) + XCTAssertTrue(json.float! == 1234567890.876623) + XCTAssertTrue(json.floatValue == 1234567890.876623) + } + + func testBool() { + var jsonTrue: JSON = true + XCTAssertEqual(jsonTrue.bool!, true) + XCTAssertEqual(jsonTrue.boolValue, true) + var jsonFalse: JSON = false + XCTAssertEqual(jsonFalse.bool!, false) + XCTAssertEqual(jsonFalse.boolValue, false) + } + + func testString() { + 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 + XCTAssert(jsonNil_1 == JSON.null) + let jsonNil_2: JSON = JSON(NSNull.self) + XCTAssert(jsonNil_2 != JSON.null) + 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"]) + } + + 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"]]) + } +} diff --git a/Tests/SwiftJSONTests/MergeTests.swift b/Tests/SwiftJSONTests/MergeTests.swift new file mode 100644 index 00000000..922c459b --- /dev/null +++ b/Tests/SwiftJSONTests/MergeTests.swift @@ -0,0 +1,97 @@ +// MergeTests.swift +// +// Created by Daniel Kiedrowski on 17.11.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 MergeTests: XCTestCase { + + func testDifferingTypes() { + let A = JSON("a") + let B = JSON(1) + + do { + _ = try A.merged(with: B) + } 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/SwiftJSONTests/NumberTests.swift b/Tests/SwiftJSONTests/NumberTests.swift new file mode 100644 index 00000000..9f919ca3 --- /dev/null +++ b/Tests/SwiftJSONTests/NumberTests.swift @@ -0,0 +1,387 @@ +// NumberTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class NumberTests: XCTestCase { + + func testNumber() { + //getter + var json = JSON(NSNumber(value: 9876543210.123456789)) + 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) + XCTAssertEqual(json.numberValue, 0) + } + + func testFloat() { + var json = JSON(54321.12345) + XCTAssertTrue(json.float! == 54321.12345) + XCTAssertTrue(json.floatValue == 54321.12345) + 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)) + + json.double = -98766.23 + XCTAssertEqual(json.float!, -98766.23) + XCTAssertEqual(json.floatValue, -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) + XCTAssertTrue(json.int8! == n127.int8Value) + XCTAssertTrue(json.int8Value == n127.int8Value) + 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) + XCTAssertTrue(json.int8Value == nm128.int8Value) + 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) + XCTAssertTrue(json.int8Value == n0.int8Value) + 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) + XCTAssertTrue(json.int8Value == n1.int8Value) + XCTAssertTrue(json.number! == n1) + XCTAssertEqual(json.numberValue, n1) + XCTAssertEqual(json.stringValue, "1") + } + + func testUInt8() { + let n255 = NSNumber(value: 255) + var json = JSON(n255) + XCTAssertTrue(json.uInt8! == n255.uint8Value) + XCTAssertTrue(json.uInt8Value == n255.uint8Value) + 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) + XCTAssertTrue(json.uInt8Value == nm2.uint8Value) + 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) + XCTAssertTrue(json.uInt8Value == nm0.uint8Value) + XCTAssertTrue(json.number! == nm0) + XCTAssertEqual(json.numberValue, nm0) + XCTAssertEqual(json.stringValue, "0") + + let nm1 = NSNumber(value: 1) + json.uInt8 = nm1.uint8Value + XCTAssertTrue(json.uInt8! == nm1.uint8Value) + XCTAssertTrue(json.uInt8Value == nm1.uint8Value) + XCTAssertTrue(json.number! == nm1) + XCTAssertEqual(json.numberValue, nm1) + XCTAssertEqual(json.stringValue, "1") + } + + func testInt16() { + + let n32767 = NSNumber(value: 32767) + var json = JSON(n32767) + XCTAssertTrue(json.int16! == n32767.int16Value) + XCTAssertTrue(json.int16Value == n32767.int16Value) + 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) + XCTAssertTrue(json.int16Value == nm32768.int16Value) + 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) + XCTAssertTrue(json.int16Value == n0.int16Value) + 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) + XCTAssertTrue(json.int16Value == n1.int16Value) + XCTAssertTrue(json.number! == n1) + XCTAssertEqual(json.numberValue, n1) + XCTAssertEqual(json.stringValue, "1") + } + + func testUInt16() { + + let n65535 = NSNumber(value: 65535) + var json = JSON(n65535) + XCTAssertTrue(json.uInt16! == n65535.uint16Value) + XCTAssertTrue(json.uInt16Value == n65535.uint16Value) + XCTAssertTrue(json.number! == n65535) + XCTAssertEqual(json.numberValue, n65535) + XCTAssertEqual(json.stringValue, "65535") + + let n32767 = NSNumber(value: 32767) + json.uInt16 = n32767.uint16Value + XCTAssertTrue(json.uInt16! == n32767.uint16Value) + XCTAssertTrue(json.uInt16Value == n32767.uint16Value) + XCTAssertTrue(json.number! == n32767) + XCTAssertEqual(json.numberValue, n32767) + XCTAssertEqual(json.stringValue, "32767") + } + + func testInt32() { + let n2147483647 = NSNumber(value: 2147483647) + var json = JSON(n2147483647) + XCTAssertTrue(json.int32! == n2147483647.int32Value) + XCTAssertTrue(json.int32Value == n2147483647.int32Value) + 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) + XCTAssertTrue(json.int32Value == n32767.int32Value) + 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) + XCTAssertTrue(json.int32Value == nm2147483648.int32Value) + XCTAssertTrue(json.number! == nm2147483648) + XCTAssertEqual(json.numberValue, nm2147483648) + XCTAssertEqual(json.stringValue, "-2147483648") + } + + func testUInt32() { + let n2147483648 = NSNumber(value: 2147483648 as UInt32) + var json = JSON(n2147483648) + XCTAssertTrue(json.uInt32! == n2147483648.uint32Value) + XCTAssertTrue(json.uInt32Value == n2147483648.uint32Value) + 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) + XCTAssertTrue(json.uInt32Value == n32767.uint32Value) + 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) + XCTAssertTrue(json.uInt32Value == n0.uint32Value) + XCTAssertTrue(json.number! == n0) + XCTAssertEqual(json.numberValue, n0) + XCTAssertEqual(json.stringValue, "0") + } + + func testInt64() { + let int64Max = NSNumber(value: INT64_MAX) + var json = JSON(int64Max) + XCTAssertTrue(json.int64! == int64Max.int64Value) + XCTAssertTrue(json.int64Value == int64Max.int64Value) + 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) + XCTAssertTrue(json.int64Value == n32767.int64Value) + 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) + XCTAssertTrue(json.int64Value == int64Min.int64Value) + XCTAssertTrue(json.number! == int64Min) + XCTAssertEqual(json.numberValue, int64Min) + XCTAssertEqual(json.stringValue, int64Min.stringValue) + } + + func testUInt64() { + let uInt64Max = NSNumber(value: UINT64_MAX) + var json = JSON(uInt64Max) + XCTAssertTrue(json.uInt64! == uInt64Max.uint64Value) + XCTAssertTrue(json.uInt64Value == uInt64Max.uint64Value) + 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) + XCTAssertTrue(json.int64Value == n32767.int64Value) + XCTAssertTrue(json.number! == n32767) + XCTAssertEqual(json.numberValue, n32767) + XCTAssertEqual(json.stringValue, "32767") + } +} diff --git a/Tests/SwiftJSONTests/PerformanceTests.swift b/Tests/SwiftJSONTests/PerformanceTests.swift new file mode 100644 index 00000000..c0e6cc0b --- /dev/null +++ b/Tests/SwiftJSONTests/PerformanceTests.swift @@ -0,0 +1,142 @@ +// PerformanceTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class PerformanceTests: XCTestCase { + + var testData: Data! + + override func setUp() { + super.setUp() + + #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 { + for _ in 1...100 { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + XCTAssertTrue(json != JSON.null) + } + } + } + + func testObjectMethodPerformance() { + 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 + XCTAssertTrue(object != nil) + } + } + } + + func testArrayMethodPerformance() { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + self.measure { + for _ in 1...100 { + autoreleasepool { + if let array = json.array { + XCTAssertTrue(array.count > 0) + } + } + } + } + } + + func testDictionaryMethodPerformance() { + guard let json = try? JSON(data: self.testData)[0] else { + XCTFail("Unable to parse testData") + return + } + self.measure { + for _ in 1...100 { + autoreleasepool { + if let dictionary = json.dictionary { + XCTAssertTrue(dictionary.count > 0) + } + } + } + } + } + + func testRawStringMethodPerformance() { + guard let json = try? JSON(data: self.testData) else { + XCTFail("Unable to parse testData") + return + } + self.measure { + for _ in 1...100 { + autoreleasepool { + let string = json.rawString() + XCTAssertTrue(string != nil) + } + } + } + } + + func testLargeDictionaryMethodPerformance() { + var data: [String: JSON] = [:] + (0...100000).forEach { n in + data["\(n)"] = JSON([ + "name": "item\(n)", + "id": n + ]) + } + let json = JSON(data) + + self.measure { + autoreleasepool { + if let dictionary = json.dictionary { + XCTAssertTrue(dictionary.count == 100001) + } else { + XCTFail("dictionary should not be nil") + } + } + } + } +} diff --git a/Tests/SwiftJSONTests/PrintableTests.swift b/Tests/SwiftJSONTests/PrintableTests.swift new file mode 100644 index 00000000..ba5863d1 --- /dev/null +++ b/Tests/SwiftJSONTests/PrintableTests.swift @@ -0,0 +1,124 @@ +// PrintableTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class PrintableTests: XCTestCase { + func testNumber() { + let json: JSON = 1234567890.876623 + XCTAssertEqual(json.description, "1234567890.876623") + XCTAssertEqual(json.debugDescription, "1234567890.876623") + } + + func testBool() { + let jsonTrue: JSON = true + XCTAssertEqual(jsonTrue.description, "true") + XCTAssertEqual(jsonTrue.debugDescription, "true") + let jsonFalse: JSON = false + XCTAssertEqual(jsonFalse.description, "false") + XCTAssertEqual(jsonFalse.debugDescription, "false") + } + + func testString() { + 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 + XCTAssertEqual(jsonNil_1.description, "null") + XCTAssertEqual(jsonNil_1.debugDescription, "null") + 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"] + var description = json.description.replacingOccurrences(of: "\n", with: "") + description = description.replacingOccurrences(of: " ", with: "") + XCTAssertEqual(description, "[1,2,\"4\",5,\"6\"]") + XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) + XCTAssertTrue(json.debugDescription.lengthOfBytes(using: String.Encoding.utf8) > 0) + } + + func testArrayWithStrings() { + let array = ["\"123\""] + let json = JSON(array) + var description = json.description.replacingOccurrences(of: "\n", with: "") + description = description.replacingOccurrences(of: " ", with: "") + XCTAssertEqual(description, "[\"\\\"123\\\"\"]") + XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) + XCTAssertTrue(json.debugDescription.lengthOfBytes(using: String.Encoding.utf8) > 0) + } + + func testArrayWithOptionals() { + 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") + return + } + description = description.replacingOccurrences(of: "\n", with: "") + description = description.replacingOccurrences(of: " ", with: "") + XCTAssertEqual(description, "[1,2,\"4\",5,\"6\",null]") + 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] + var debugDescription = json.debugDescription.replacingOccurrences(of: "\n", with: "") + debugDescription = debugDescription.replacingOccurrences(of: " ", with: "") + XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) + XCTAssertTrue(debugDescription.range(of: "\"1\":2", options: String.CompareOptions.caseInsensitive) != nil) + XCTAssertTrue(debugDescription.range(of: "\"2\":\"two\"", options: String.CompareOptions.caseInsensitive) != nil) + XCTAssertTrue(debugDescription.range(of: "\"3\":3", options: String.CompareOptions.caseInsensitive) != nil) + } + + func testDictionaryWithStrings() { + 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: "") + XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) + let exceptedResult = "{\"foo\":\"{\\\"bar\\\":123}\"}" + XCTAssertEqual(debugDescription, exceptedResult) + } + + func testDictionaryWithOptionals() { + 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") + return + } + description = description.replacingOccurrences(of: "\n", with: "") + description = description.replacingOccurrences(of: " ", with: "") + XCTAssertTrue(json.description.lengthOfBytes(using: String.Encoding.utf8) > 0) + XCTAssertTrue(description.range(of: "\"1\":2", options: NSString.CompareOptions.caseInsensitive) != nil) + XCTAssertTrue(description.range(of: "\"2\":\"two\"", options: NSString.CompareOptions.caseInsensitive) != nil) + XCTAssertTrue(description.range(of: "\"3\":null", options: NSString.CompareOptions.caseInsensitive) != nil) + } +} diff --git a/Tests/SwiftJSONTests/RawRepresentableTests.swift b/Tests/SwiftJSONTests/RawRepresentableTests.swift new file mode 100644 index 00000000..88a70de8 --- /dev/null +++ b/Tests/SwiftJSONTests/RawRepresentableTests.swift @@ -0,0 +1,114 @@ +// RawRepresentableTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class RawRepresentableTests: XCTestCase { + + func testNumber() { + 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) + XCTAssertEqual(json.float!, 948394394.347384) + XCTAssertEqual(json.floatValue, 948394394.347384) + + let object: Any = json.rawValue + if let int = object as? Int { + XCTAssertEqual(int, 948394394) + } + XCTAssertEqual(object as? Double, 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)! + XCTAssertEqual(jsonTrue.bool!, true) + XCTAssertEqual(jsonTrue.boolValue, true) + + 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) { + XCTAssertEqual(json.string!, string) + XCTAssertEqual(json.stringValue, string) + XCTAssertTrue(json.array == nil) + XCTAssertTrue(json.dictionary == nil) + XCTAssertTrue(json.null == nil) + XCTAssertTrue(json.error == nil) + XCTAssertTrue(json.type == .string) + XCTAssertEqual(json.object as? String, string) + } else { + XCTFail("Should not run into here") + } + + let object: Any = JSON(rawValue: string)!.rawValue + XCTAssertEqual(object as? String, string) + } + + func testNil() { + 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) { + 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) { + XCTAssertEqual(json, JSON(dictionary)) + } + + let object: Any = JSON(rawValue: dictionary)!.rawValue + XCTAssertTrue(dictionary == object as! NSDictionary) + } +} diff --git a/Tests/SwiftJSONTests/RawTests.swift b/Tests/SwiftJSONTests/RawTests.swift new file mode 100644 index 00000000..036060fb --- /dev/null +++ b/Tests/SwiftJSONTests/RawTests.swift @@ -0,0 +1,105 @@ +// RawTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class RawTests: XCTestCase { + + func testRawData() { + 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 _ {} + } + + func testInvalidJSONForRawData() { + let json: JSON = "...xyz" + do { + _ = try json.rawData() + } catch let error as SwiftyJSONError { + XCTAssertEqual(error, SwiftyJSONError.invalidJSON) + } catch _ {} + } + + func testArray() { + let json: JSON = [1, "2", 3.12, NSNull(), true, ["name": "Jack"]] + let data: Data? + do { + data = try json.rawData() + } catch _ { + data = nil + } + let string = json.rawString() + XCTAssertTrue (data != nil) + XCTAssertTrue (string!.lengthOfBytes(using: String.Encoding.utf8) > 0) + } + + func testDictionary() { + 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() + } catch _ { + data = nil + } + let string = json.rawString() + XCTAssertTrue (data != nil) + XCTAssertTrue (string!.lengthOfBytes(using: String.Encoding.utf8) > 0) + } + + func testString() { + let json: JSON = "I'm a json" + XCTAssertEqual(json.rawString(), "I'm a json") + } + + func testNumber() { + let json: JSON = 123456789.123 + XCTAssertEqual(json.rawString(), "123456789.123") + } + + func testBool() { + let json: JSON = true + XCTAssertEqual(json.rawString(), "true") + } + + func testNull() { + 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/SwiftJSONTests/SequenceTypeTests.swift b/Tests/SwiftJSONTests/SequenceTypeTests.swift new file mode 100644 index 00000000..a039453f --- /dev/null +++ b/Tests/SwiftJSONTests/SequenceTypeTests.swift @@ -0,0 +1,247 @@ +// SequenceTypeTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class SequenceTypeTests: XCTestCase { + + var testData: Data? + + func testJSONFile() { + #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: + XCTAssertTrue(sub["id_str"] == "240558470661799936") + case 1: + XCTAssertTrue(sub["id_str"] == "240556426106372096") + case 2: + XCTAssertTrue(sub["id_str"] == "240539141056638977") + default: + continue + } + } + } else { + XCTFail("Can't find the test JSON file") + } + } + + func testArrayAllNumber() { + var json: JSON = [1, 2.0, 3.3, 123456789, 987654321.123456789] + XCTAssertEqual(json.count, 5) + + var index = 0 + var array = [NSNumber]() + for (i, sub) in json { + XCTAssertEqual(sub, json[index]) + XCTAssertEqual(i, "\(index)") + array.append(sub.number!) + index += 1 + } + XCTAssertEqual(index, 5) + XCTAssertEqual(array, [1, 2.0, 3.3, 123456789, 987654321.123456789]) + } + + func testArrayAllBool() { + var json: JSON = JSON([true, false, false, true, true]) + XCTAssertEqual(json.count, 5) + + var index = 0 + var array = [Bool]() + for (i, sub) in json { + XCTAssertEqual(sub, json[index]) + XCTAssertEqual(i, "\(index)") + array.append(sub.bool!) + index += 1 + } + XCTAssertEqual(index, 5) + XCTAssertEqual(array, [true, false, false, true, true]) + } + + func testArrayAllString() { + var json: JSON = JSON(rawValue: ["aoo", "bpp", "zoo"] as NSArray)! + XCTAssertEqual(json.count, 3) + + var index = 0 + var array = [String]() + for (i, sub) in json { + XCTAssertEqual(sub, json[index]) + XCTAssertEqual(i, "\(index)") + array.append(sub.string!) + index += 1 + } + XCTAssertEqual(index, 3) + XCTAssertEqual(array, ["aoo", "bpp", "zoo"]) + } + + func testArrayWithNull() { + var json: JSON = JSON(rawValue: ["aoo", "bpp", NSNull(), "zoo"] as NSArray)! + XCTAssertEqual(json.count, 4) + + var index = 0 + var array = [AnyObject]() + for (i, sub) in json { + XCTAssertEqual(sub, json[index]) + XCTAssertEqual(i, "\(index)") + array.append(sub.object as AnyObject) + index += 1 + } + XCTAssertEqual(index, 4) + XCTAssertEqual(array[0] as? String, "aoo") + XCTAssertEqual(array[2] as? NSNull, NSNull()) + } + + func testArrayAllDictionary() { + var json: JSON = [["1": 1, "2": 2], ["a": "A", "b": "B"], ["null": NSNull()]] + XCTAssertEqual(json.count, 3) + + var index = 0 + var array = [AnyObject]() + for (i, sub) in json { + XCTAssertEqual(sub, json[index]) + XCTAssertEqual(i, "\(index)") + array.append(sub.object as AnyObject) + 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()) + } + + func testDictionaryAllNumber() { + var json: JSON = ["double": 1.11111, "int": 987654321] + XCTAssertEqual(json.count, 2) + + var index = 0 + var dictionary = [String: NSNumber]() + for (key, sub) in json { + XCTAssertEqual(sub, json[key]) + dictionary[key] = sub.number! + index += 1 + } + + XCTAssertEqual(index, 2) + XCTAssertEqual(dictionary["double"]! as NSNumber, 1.11111) + XCTAssertEqual(dictionary["int"]! as NSNumber, 987654321) + } + + func testDictionaryAllBool() { + var json: JSON = ["t": true, "f": false, "false": false, "tr": true, "true": true] + XCTAssertEqual(json.count, 5) + + var index = 0 + var dictionary = [String: Bool]() + for (key, sub) in json { + XCTAssertEqual(sub, json[key]) + dictionary[key] = sub.bool! + index += 1 + } + + XCTAssertEqual(index, 5) + XCTAssertEqual(dictionary["t"]! as Bool, true) + XCTAssertEqual(dictionary["false"]! as Bool, false) + } + + func testDictionaryAllString() { + var json: JSON = JSON(rawValue: ["a": "aoo", "bb": "bpp", "z": "zoo"] as NSDictionary)! + XCTAssertEqual(json.count, 3) + + var index = 0 + var dictionary = [String: String]() + for (key, sub) in json { + XCTAssertEqual(sub, json[key]) + dictionary[key] = sub.string! + index += 1 + } + + XCTAssertEqual(index, 3) + XCTAssertEqual(dictionary["a"]! as String, "aoo") + XCTAssertEqual(dictionary["bb"]! as String, "bpp") + } + + func testDictionaryWithNull() { + 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]() + for (key, sub) in json { + XCTAssertEqual(sub, json[key]) + dictionary[key] = sub.object as AnyObject? + index += 1 + } + + XCTAssertEqual(index, 4) + XCTAssertEqual(dictionary["a"]! as? String, "aoo") + XCTAssertEqual(dictionary["bb"]! as? String, "bpp") + XCTAssertEqual(dictionary["null"]! as? NSNull, NSNull()) + } + + 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]]) + + XCTAssertEqual(json.count, 3) + + var index = 0 + var dictionary = [String: AnyObject]() + for (key, sub) in json { + XCTAssertEqual(sub, json[key]) + dictionary[key] = sub.object as AnyObject? + index += 1 + } + + XCTAssertEqual(index, 3) + XCTAssertEqual((dictionary["Number"] as! NSArray)[0] as? Int, 1) + XCTAssertEqual((dictionary["Number"] as! NSArray)[1] as? Double, 2.123456) + XCTAssertEqual((dictionary["String"] as! NSArray)[0] as? String, "aa") + XCTAssertEqual((dictionary["Mix"] as! NSArray)[0] as? Bool, true) + XCTAssertEqual((dictionary["Mix"] as! NSArray)[1] as? String, "766") + XCTAssertEqual((dictionary["Mix"] as! NSArray)[2] as? NSNull, NSNull()) + XCTAssertEqual((dictionary["Mix"] as! NSArray)[3] as? Double, 655231.9823) + } + + func testDictionaryIteratingPerformance() { + var json: JSON = [:] + for i in 1...1000 { + json[String(i)] = "hello" + } + measure { + for (key, value) in json { + print(key, value) + } + } + } +} diff --git a/Tests/SwiftJSONTests/StringTests.swift b/Tests/SwiftJSONTests/StringTests.swift new file mode 100644 index 00000000..9ce10643 --- /dev/null +++ b/Tests/SwiftJSONTests/StringTests.swift @@ -0,0 +1,80 @@ +// StringTests.swift +// +// Copyright (c) 2014 - 2017 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 + +class StringTests: XCTestCase { + + func testString() { + //getter + var json = JSON("abcdefg hijklmn;opqrst.?+_()") + XCTAssertEqual(json.string!, "abcdefg hijklmn;opqrst.?+_()") + XCTAssertEqual(json.stringValue, "abcdefg hijklmn;opqrst.?+_()") + + json.string = "12345?67890.@#" + 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")!) + } + + func testBool() { + let json = JSON("true") + XCTAssertTrue(json.boolValue) + } + + func testBoolWithY() { + let json = JSON("Y") + XCTAssertTrue(json.boolValue) + } + + func testBoolWithT() { + let json = JSON("T") + 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" + guard let encodedURLString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { + return XCTFail("Couldn't encode URL string \(urlString)") + } + let json = JSON(urlString) + XCTAssertEqual(json.url!, URL(string: encodedURLString)!, "Wrong unpacked ") + let preEscaped = JSON(encodedURLString) + XCTAssertEqual(preEscaped.url!, URL(string: encodedURLString)!, "Wrong unpacked ") + } +} diff --git a/Tests/SwiftJSONTests/SubscriptTests.swift b/Tests/SwiftJSONTests/SubscriptTests.swift new file mode 100644 index 00000000..5b399f40 --- /dev/null +++ b/Tests/SwiftJSONTests/SubscriptTests.swift @@ -0,0 +1,267 @@ +// SubscriptTests.swift +// +// Copyright (c) 2014 - 2017 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 + +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]) + 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] + 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"]) + 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)! + 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") + XCTAssertTrue(json[1] == "bpp") + XCTAssertTrue(json[2] == "update") + 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()])) + 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"] + XCTAssertEqual(json[keys], JSON(rawValue: "A")!) + } + + func testDictionaryAllNumber() { + 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 + XCTAssertTrue(json["double"] == 2.2222) + 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, "yes": true, "1": true] + XCTAssertTrue(json["1"] == true) + XCTAssertTrue(json["yes"] == true) + XCTAssertTrue(json["t"] == true) + XCTAssertTrue(json["f"] == false) + XCTAssertTrue(json["false"] == false) + XCTAssertTrue(json["tr"] == true) + XCTAssertTrue(json["true"] == true) + + json["f"] = true + json["tr"] = false + XCTAssertTrue(json["f"] == true) + XCTAssertTrue(json["tr"] == JSON(false)) + } + + func testDictionaryAllString() { + 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)! + 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]) + 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[2][0] == true) + 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][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) + XCTAssertEqual(json[9], JSON.null) + XCTAssertEqual(json[-2].error, SwiftyJSONError.indexOutOfBounds) + XCTAssertEqual(json[6].error, SwiftyJSONError.indexOutOfBounds) + XCTAssertEqual(json[9][8], JSON.null) + 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, SwiftyJSONError.wrongType) + XCTAssertEqual(json[8][7].error, SwiftyJSONError.wrongType) + XCTAssertEqual(json["name"], JSON.null) + 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] + XCTAssertEqual(json["Type"], JSON.null) + 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]]]]] + 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]]]]] + 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") + 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"] + 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]) + } +} diff --git a/Tests/SwiftJSONTests/Tests.json b/Tests/SwiftJSONTests/Tests.json new file mode 100644 index 00000000..05190a8a --- /dev/null +++ b/Tests/SwiftJSONTests/Tests.json @@ -0,0 +1,345 @@ +[ + { + "coordinates":null, + "truncated":false, + "created_at":"Tue Aug 28 21:16:23 +0000 2012", + "favorited":false, + "id_str":"240558470661799936", + "in_reply_to_user_id_str":null, + "entities":{ + "urls":[ + + ], + "hashtags":[ + + ], + "user_mentions":[ + + ] + }, + "text":"just another test", + "contributors":null, + "id":240558470661799936, + "retweet_count":0, + "in_reply_to_status_id_str":null, + "geo":null, + "retweeted":false, + "in_reply_to_user_id":null, + "place":null, + "source":"<a href=\"//realitytechnicians.com\" rel=\"\"nofollow\"\">OAuth Dancer Reborn</a>", + "user":{ + "name":"OAuth Dancer", + "profile_sidebar_fill_color":"DDEEF6", + "profile_background_tile":true, + "profile_sidebar_border_color":"C0DEED", + "profile_image_url":"http://a0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg", + "created_at":"Wed Mar 03 19:37:35 +0000 2010", + "location":"San Francisco, CA", + "follow_request_sent":false, + "id_str":"119476949", + "is_translator":false, + "profile_link_color":"0084B4", + "entities":{ + "url":{ + "urls":[ + { + "expanded_url":null, + "url":"http://bit.ly/oauth-dancer", + "indices":[ + 0, + 26 + ], + "display_url":null + } + ] + }, + "description":null + }, + "default_profile":false, + "url":"http://bit.ly/oauth-dancer", + "contributors_enabled":false, + "favourites_count":7, + "utc_offset":null, + "profile_image_url_https":"https://si0.twimg.com/profile_images/730275945/oauth-dancer_normal.jpg", + "id":119476949, + "listed_count":1, + "profile_use_background_image":true, + "profile_text_color":"333333", + "followers_count":28, + "lang":"en", + "protected":false, + "geo_enabled":true, + "notifications":false, + "description":"", + "profile_background_color":"C0DEED", + "verified":false, + "time_zone":null, + "profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/80151733/oauth-dance.png", + "statuses_count":166, + "profile_background_image_url":"http://a0.twimg.com/profile_background_images/80151733/oauth-dance.png", + "default_profile_image":false, + "friends_count":14, + "following":false, + "show_all_inline_media":false, + "screen_name":"oauth_dancer" + }, + "in_reply_to_screen_name":null, + "in_reply_to_status_id":null + }, + { + "coordinates":{ + "coordinates":[ + -122.25831, + 37.871609 + ], + "type":"Point" + }, + "truncated":false, + "created_at":"Tue Aug 28 21:08:15 +0000 2012", + "favorited":false, + "id_str":"240556426106372096", + "in_reply_to_user_id_str":null, + "entities":{ + "urls":[ + { + "expanded_url":"http://blogs.ischool.berkeley.edu/i290-abdt-s12/", + "url":"http://t.co/bfj7zkDJ", + "indices":[ + 79, + 99 + ], + "display_url":"blogs.ischool.berkeley.edu/i290-abdt-s12/" + } + ], + "hashtags":[ + + ], + "user_mentions":[ + { + "name":"Cal", + "id_str":"17445752", + "id":17445752, + "indices":[ + 60, + 64 + ], + "screen_name":"Cal" + }, + { + "name":"Othman Laraki", + "id_str":"20495814", + "id":20495814, + "indices":[ + 70, + 77 + ], + "screen_name":"othman" + } + ] + }, + "text":"lecturing at the \"analyzing big data with twitter\" class at @cal with @othman http://t.co/bfj7zkDJ", + "contributors":null, + "id":240556426106372096, + "retweet_count":3, + "in_reply_to_status_id_str":null, + "geo":{ + "coordinates":[ + 37.871609, + -122.25831 + ], + "type":"Point" + }, + "retweeted":false, + "possibly_sensitive":false, + "in_reply_to_user_id":null, + "place":{ + "name":"Berkeley", + "country_code":"US", + "country":"United States", + "attributes":{ + + }, + "url":"http://api.twitter.com/1/geo/id/5ef5b7f391e30aff.json", + "id":"5ef5b7f391e30aff", + "bounding_box":{ + "coordinates":[ + [ + [ + -122.367781, + 37.835727 + ], + [ + -122.234185, + 37.835727 + ], + [ + -122.234185, + 37.905824 + ], + [ + -122.367781, + 37.905824 + ] + ] + ], + "type":"Polygon" + }, + "full_name":"Berkeley, CA", + "place_type":"city" + }, + "source":"<a href=\"//www.apple.com\"\" rel=\"\"nofollow\"\">Safari on iOS</a>", + "user":{ + "name":"Raffi Krikorian", + "profile_sidebar_fill_color":"DDEEF6", + "profile_background_tile":false, + "profile_sidebar_border_color":"C0DEED", + "profile_image_url":"http://a0.twimg.com/profile_images/1270234259/raffi-headshot-casual_normal.png", + "created_at":"Sun Aug 19 14:24:06 +0000 2007", + "location":"San Francisco, California", + "follow_request_sent":false, + "id_str":"8285392", + "is_translator":false, + "profile_link_color":"0084B4", + "entities":{ + "url":{ + "urls":[ + { + "expanded_url":"http://about.me/raffi.krikorian", + "url":"http://t.co/eNmnM6q", + "indices":[ + 0, + 19 + ], + "display_url":"about.me/raffi.krikorian" + } + ] + }, + "description":{ + "urls":[ + + ] + } + }, + "default_profile":true, + "url":"http://t.co/eNmnM6q", + "contributors_enabled":false, + "favourites_count":724, + "utc_offset":-28800, + "profile_image_url_https":"https://si0.twimg.com/profile_images/1270234259/raffi-headshot-casual_normal.png", + "id":8285392, + "listed_count":619, + "profile_use_background_image":true, + "profile_text_color":"333333", + "followers_count":18752, + "lang":"en", + "protected":false, + "geo_enabled":true, + "notifications":false, + "description":"Director of @twittereng's Platform Services. I break things.", + "profile_background_color":"C0DEED", + "verified":false, + "time_zone":"Pacific Time (US & Canada)", + "profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png", + "statuses_count":5007, + "profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png", + "default_profile_image":false, + "friends_count":701, + "following":true, + "show_all_inline_media":true, + "screen_name":"raffi" + }, + "in_reply_to_screen_name":null, + "in_reply_to_status_id":null + }, + { + "coordinates":null, + "truncated":false, + "created_at":"Tue Aug 28 19:59:34 +0000 2012", + "favorited":false, + "id_str":"240539141056638977", + "in_reply_to_user_id_str":null, + "entities":{ + "urls":[ + + ], + "hashtags":[ + + ], + "user_mentions":[ + + ] + }, + "text":"You'd be right more often if you thought you were wrong.", + "contributors":null, + "id":240539141056638977, + "retweet_count":1, + "in_reply_to_status_id_str":null, + "geo":null, + "retweeted":false, + "in_reply_to_user_id":null, + "place":null, + "source":"web", + "user":{ + "name":"Taylor Singletary", + "profile_sidebar_fill_color":"FBFBFB", + "profile_background_tile":true, + "profile_sidebar_border_color":"000000", + "profile_image_url":"http://a0.twimg.com/profile_images/2546730059/f6a8zq58mg1hn0ha8vie_normal.jpeg", + "created_at":"Wed Mar 07 22:23:19 +0000 2007", + "location":"San Francisco, CA", + "follow_request_sent":false, + "id_str":"819797", + "is_translator":false, + "profile_link_color":"c71818", + "entities":{ + "url":{ + "urls":[ + { + "expanded_url":"http://www.rebelmouse.com/episod/", + "url":"http://t.co/Lxw7upbN", + "indices":[ + 0, + 20 + ], + "display_url":"rebelmouse.com/episod/" + } + ] + }, + "description":{ + "urls":[ + + ] + } + }, + "default_profile":false, + "url":"http://t.co/Lxw7upbN", + "contributors_enabled":false, + "favourites_count":15990, + "utc_offset":-28800, + "profile_image_url_https":"https://si0.twimg.com/profile_images/2546730059/f6a8zq58mg1hn0ha8vie_normal.jpeg", + "id":819797, + "listed_count":340, + "profile_use_background_image":true, + "profile_text_color":"D20909", + "followers_count":7126, + "lang":"en", + "protected":false, + "geo_enabled":true, + "notifications":false, + "description":"Reality Technician, Twitter API team, synthesizer enthusiast; a most excellent adventure in timelines. I know it's hard to believe in something you can't see.", + "profile_background_color":"000000", + "verified":false, + "time_zone":"Pacific Time (US & Canada)", + "profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/643655842/hzfv12wini4q60zzrthg.png", + "statuses_count":18076, + "profile_background_image_url":"http://a0.twimg.com/profile_background_images/643655842/hzfv12wini4q60zzrthg.png", + "default_profile_image":false, + "friends_count":5444, + "following":true, + "show_all_inline_media":true, + "screen_name":"episod" + }, + "in_reply_to_screen_name":null, + "in_reply_to_status_id":null + } + ] \ No newline at end of file