├── .gitignore ├── .ruby-version ├── .swift-version ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── JSONHelper.podspec ├── JSONHelper.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── JSONHelper.xccheckout └── xcshareddata │ └── xcschemes │ ├── JSONHelper.xcscheme │ └── JSONHelperExample.xcscheme ├── JSONHelper ├── Conversion.swift ├── Deserialization.swift ├── Extensions │ ├── Bool.swift │ ├── Color.swift │ ├── Date.swift │ ├── DecimalNumber.swift │ ├── Double.swift │ ├── Float.swift │ ├── Int.swift │ ├── String.swift │ └── URL.swift ├── JSONHelper.h ├── JSONHelper.swift ├── Serialization.swift ├── Support │ └── JSONAPI.swift └── Supporting Files │ ├── Mac │ └── Info.plist │ ├── iOS │ └── Info.plist │ └── tvOS │ ├── Info.plist │ └── JSONHelper-tvOS.h ├── JSONHelperExample ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Supporting Files │ └── Info.plist └── ViewController.swift ├── JSONHelperExampleTests ├── JSONHelperExampleTests.swift └── Supporting Files │ └── Info.plist ├── JSONHelperTests ├── ArrayTests.swift ├── BoolTests.swift ├── ColorTests.swift ├── DateTests.swift ├── DecimalTests.swift ├── DeserializableTests.swift ├── DictionaryTests.swift ├── DoubleTests.swift ├── EnumTests.swift ├── FloatTests.swift ├── IntTests.swift ├── JSONHelperTests.swift ├── StringTests.swift ├── Supporting Files │ └── Info.plist └── URLTests.swift ├── LICENSE ├── README.md └── scripts ├── install-fast.sh ├── install-travis.sh ├── install.sh ├── pod-lint.sh ├── pod-push.sh └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | # 3 | *.swp 4 | 5 | # OSX 6 | # 7 | .DS_Store 8 | Iconr 9 | Icon? 10 | 11 | ## Windows 12 | # 13 | desktop.ini 14 | 15 | # Xcode 16 | # 17 | build/ 18 | *.pbxuser 19 | !default.pbxuser 20 | *.mode1v3 21 | !default.mode1v3 22 | *.mode2v3 23 | !default.mode2v3 24 | *.perspectivev3 25 | !default.perspectivev3 26 | xcuserdata 27 | *.xccheckout 28 | *.moved-aside 29 | DerivedData 30 | *.hmap 31 | *.ipa 32 | *.xcuserstate 33 | project.xcworkspace 34 | 35 | # bundler 36 | .bundle 37 | vendor/bundle/ 38 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3.1 2 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.3 3 | install: 4 | - ./scripts/install-travis.sh 5 | script: 6 | - ./scripts/test.sh 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'cocoapods' 4 | gem 'xcpretty' 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (2.3.5) 5 | activesupport (4.2.8) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | thread_safe (~> 0.3, >= 0.3.4) 9 | tzinfo (~> 1.1) 10 | claide (1.0.1) 11 | cocoapods (1.2.1) 12 | activesupport (>= 4.0.2, < 5) 13 | claide (>= 1.0.1, < 2.0) 14 | cocoapods-core (= 1.2.1) 15 | cocoapods-deintegrate (>= 1.0.1, < 2.0) 16 | cocoapods-downloader (>= 1.1.3, < 2.0) 17 | cocoapods-plugins (>= 1.0.0, < 2.0) 18 | cocoapods-search (>= 1.0.0, < 2.0) 19 | cocoapods-stats (>= 1.0.0, < 2.0) 20 | cocoapods-trunk (>= 1.2.0, < 2.0) 21 | cocoapods-try (>= 1.1.0, < 2.0) 22 | colored2 (~> 3.1) 23 | escape (~> 0.0.4) 24 | fourflusher (~> 2.0.1) 25 | gh_inspector (~> 1.0) 26 | molinillo (~> 0.5.7) 27 | nap (~> 1.0) 28 | ruby-macho (~> 1.1) 29 | xcodeproj (>= 1.4.4, < 2.0) 30 | cocoapods-core (1.2.1) 31 | activesupport (>= 4.0.2, < 5) 32 | fuzzy_match (~> 2.0.4) 33 | nap (~> 1.0) 34 | cocoapods-deintegrate (1.0.1) 35 | cocoapods-downloader (1.1.3) 36 | cocoapods-plugins (1.0.0) 37 | nap 38 | cocoapods-search (1.0.0) 39 | cocoapods-stats (1.0.0) 40 | cocoapods-trunk (1.2.0) 41 | nap (>= 0.8, < 2.0) 42 | netrc (= 0.7.8) 43 | cocoapods-try (1.1.0) 44 | colored2 (3.1.2) 45 | escape (0.0.4) 46 | fourflusher (2.0.1) 47 | fuzzy_match (2.0.4) 48 | gh_inspector (1.0.3) 49 | i18n (0.8.1) 50 | minitest (5.10.1) 51 | molinillo (0.5.7) 52 | nanaimo (0.2.3) 53 | nap (1.1.0) 54 | netrc (0.7.8) 55 | rouge (2.0.7) 56 | ruby-macho (1.1.0) 57 | thread_safe (0.3.6) 58 | tzinfo (1.2.3) 59 | thread_safe (~> 0.1) 60 | xcodeproj (1.4.4) 61 | CFPropertyList (~> 2.3.3) 62 | claide (>= 1.0.1, < 2.0) 63 | colored2 (~> 3.1) 64 | nanaimo (~> 0.2.3) 65 | xcpretty (0.2.7) 66 | rouge (~> 2.0.7) 67 | 68 | PLATFORMS 69 | ruby 70 | 71 | DEPENDENCIES 72 | cocoapods 73 | xcpretty 74 | 75 | BUNDLED WITH 76 | 1.14.6 77 | -------------------------------------------------------------------------------- /JSONHelper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'JSONHelper' 3 | s.version = '2.2.0' 4 | s.license = { :type => 'zlib', :file => 'LICENSE' } 5 | 6 | s.summary = 'Convert values of any type into any other type in just one operation!' 7 | s.description = 'Convert anything into anything in one operation; hex strings into UIColor/NSColor, JSON strings into class instances, y/n strings to booleans, arrays and dictionaries of these; anything you can make sense of!' 8 | 9 | s.homepage = 'https://github.com/isair/JSONHelper' 10 | s.author = { 'Baris Sencan' => 'baris.sncn@gmail.com' } 11 | s.social_media_url = 'https://twitter.com/IsairAndMorty' 12 | 13 | s.ios.deployment_target = '8.0' 14 | s.osx.deployment_target = '10.9' 15 | s.tvos.deployment_target = '9.0' 16 | s.source = { :git => 'https://github.com/isair/JSONHelper.git', :tag => s.version } 17 | s.source_files = 'JSONHelper/**/*.swift' 18 | s.frameworks = 'Foundation' 19 | s.requires_arc = true 20 | end 21 | -------------------------------------------------------------------------------- /JSONHelper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5F024AE11B4127C900EF50C4 /* IntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F024AE01B4127C900EF50C4 /* IntTests.swift */; }; 11 | 5F024AE31B412BA900EF50C4 /* BoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F024AE21B412BA900EF50C4 /* BoolTests.swift */; }; 12 | 5F133DA21C3840BB00EF50C4 /* JSONAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F133DA11C3840BB00EF50C4 /* JSONAPI.swift */; }; 13 | 5F31FF561C5339B900EF50C4 /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF551C5339B900EF50C4 /* DateTests.swift */; }; 14 | 5F31FF581C5339CE00EF50C4 /* URLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF571C5339CE00EF50C4 /* URLTests.swift */; }; 15 | 5F31FF5C1C533AD400EF50C4 /* Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5B1C533AD400EF50C4 /* Conversion.swift */; }; 16 | 5F31FF5E1C533AE000EF50C4 /* Deserialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5D1C533AE000EF50C4 /* Deserialization.swift */; }; 17 | 5F31FF601C533E9900EF50C4 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5F1C533E9900EF50C4 /* Color.swift */; }; 18 | 5F31FF6C1C533F1600EF50C4 /* ColorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6B1C533F1600EF50C4 /* ColorTests.swift */; }; 19 | 5F31FF6E1C5348F000EF50C4 /* DecimalNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6D1C5348F000EF50C4 /* DecimalNumber.swift */; }; 20 | 5F31FF721C5348FE00EF50C4 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF711C5348FE00EF50C4 /* Double.swift */; }; 21 | 5F31FF761C53490B00EF50C4 /* Float.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF751C53490B00EF50C4 /* Float.swift */; }; 22 | 5F31FF7A1C53496B00EF50C4 /* DoubleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF791C53496B00EF50C4 /* DoubleTests.swift */; }; 23 | 5F31FF7C1C53497600EF50C4 /* FloatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF7B1C53497600EF50C4 /* FloatTests.swift */; }; 24 | 5F31FF7E1C53499000EF50C4 /* DecimalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF7D1C53499000EF50C4 /* DecimalTests.swift */; }; 25 | 5F6A2F4A1CC0116D00EF50C4 /* JSONHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F491CC0116D00EF50C4 /* JSONHelper.swift */; }; 26 | 5F6A2F4E1CC096DA00EF50C4 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */; }; 27 | 5F6A2F531CC09B9A00EF50C4 /* DeserializableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F521CC09B9A00EF50C4 /* DeserializableTests.swift */; }; 28 | 5F8F88231CA5F32E00EF50C4 /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F8F88221CA5F32E00EF50C4 /* DictionaryTests.swift */; }; 29 | 5F8F88251CA5F33500EF50C4 /* EnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F8F88241CA5F33500EF50C4 /* EnumTests.swift */; }; 30 | 5FAD076A1A70F2FC00C4D09E /* JSONHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FAD07691A70F2FC00C4D09E /* JSONHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; 31 | 5FAD07701A70F2FC00C4D09E /* JSONHelper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FAD07641A70F2FC00C4D09E /* JSONHelper.framework */; }; 32 | 5FAD07771A70F2FC00C4D09E /* JSONHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FAD07761A70F2FC00C4D09E /* JSONHelperTests.swift */; }; 33 | 5FAD07891A70F31300C4D09E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FAD07881A70F31300C4D09E /* AppDelegate.swift */; }; 34 | 5FAD078B1A70F31300C4D09E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FAD078A1A70F31300C4D09E /* ViewController.swift */; }; 35 | 5FAD078E1A70F31300C4D09E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5FAD078C1A70F31300C4D09E /* Main.storyboard */; }; 36 | 5FAD07901A70F31300C4D09E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5FAD078F1A70F31300C4D09E /* Images.xcassets */; }; 37 | 5FAD07931A70F31300C4D09E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5FAD07911A70F31300C4D09E /* LaunchScreen.xib */; }; 38 | 5FB9D4E01B38007C00EF50C4 /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FB9D4DF1B38007C00EF50C4 /* StringTests.swift */; }; 39 | 5FC1A4871B1CFFB500EF50C4 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4861B1CFFB500EF50C4 /* String.swift */; }; 40 | 5FC1A4891B1D024500EF50C4 /* Int.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4881B1D024500EF50C4 /* Int.swift */; }; 41 | 5FC1A48E1B1D057B00EF50C4 /* Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A48D1B1D057B00EF50C4 /* Bool.swift */; }; 42 | 5FC1A4901B1D082500EF50C4 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A48F1B1D082500EF50C4 /* Date.swift */; }; 43 | 5FC1A4941B1D1D8B00EF50C4 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4931B1D1D8B00EF50C4 /* URL.swift */; }; 44 | 5FD3A0A01CA5F5C300EF50C4 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FD3A09F1CA5F5C300EF50C4 /* ArrayTests.swift */; }; 45 | /* End PBXBuildFile section */ 46 | 47 | /* Begin PBXContainerItemProxy section */ 48 | 5F0E6F941ACDD94E00D92679 /* PBXContainerItemProxy */ = { 49 | isa = PBXContainerItemProxy; 50 | containerPortal = 5FAD075B1A70F2FC00C4D09E /* Project object */; 51 | proxyType = 1; 52 | remoteGlobalIDString = 5FAD07631A70F2FC00C4D09E; 53 | remoteInfo = JSONHelper; 54 | }; 55 | 5FAD07711A70F2FC00C4D09E /* PBXContainerItemProxy */ = { 56 | isa = PBXContainerItemProxy; 57 | containerPortal = 5FAD075B1A70F2FC00C4D09E /* Project object */; 58 | proxyType = 1; 59 | remoteGlobalIDString = 5FAD07631A70F2FC00C4D09E; 60 | remoteInfo = JSONHelper; 61 | }; 62 | /* End PBXContainerItemProxy section */ 63 | 64 | /* Begin PBXFileReference section */ 65 | 5F024AE01B4127C900EF50C4 /* IntTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntTests.swift; sourceTree = ""; }; 66 | 5F024AE21B412BA900EF50C4 /* BoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoolTests.swift; sourceTree = ""; }; 67 | 5F0E6F961ACDE06400D92679 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 68 | 5F133DA11C3840BB00EF50C4 /* JSONAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONAPI.swift; path = Support/JSONAPI.swift; sourceTree = ""; }; 69 | 5F31FF551C5339B900EF50C4 /* DateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = ""; }; 70 | 5F31FF571C5339CE00EF50C4 /* URLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLTests.swift; sourceTree = ""; }; 71 | 5F31FF5B1C533AD400EF50C4 /* Conversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Conversion.swift; sourceTree = ""; }; 72 | 5F31FF5D1C533AE000EF50C4 /* Deserialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Deserialization.swift; sourceTree = ""; }; 73 | 5F31FF5F1C533E9900EF50C4 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Color.swift; path = Extensions/Color.swift; sourceTree = ""; }; 74 | 5F31FF6B1C533F1600EF50C4 /* ColorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorTests.swift; sourceTree = ""; }; 75 | 5F31FF6D1C5348F000EF50C4 /* DecimalNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DecimalNumber.swift; path = Extensions/DecimalNumber.swift; sourceTree = ""; }; 76 | 5F31FF711C5348FE00EF50C4 /* Double.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Double.swift; path = Extensions/Double.swift; sourceTree = ""; }; 77 | 5F31FF751C53490B00EF50C4 /* Float.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Float.swift; path = Extensions/Float.swift; sourceTree = ""; }; 78 | 5F31FF791C53496B00EF50C4 /* DoubleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoubleTests.swift; sourceTree = ""; }; 79 | 5F31FF7B1C53497600EF50C4 /* FloatTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatTests.swift; sourceTree = ""; }; 80 | 5F31FF7D1C53499000EF50C4 /* DecimalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecimalTests.swift; sourceTree = ""; }; 81 | 5F6A2F491CC0116D00EF50C4 /* JSONHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONHelper.swift; sourceTree = ""; }; 82 | 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Serialization.swift; sourceTree = ""; }; 83 | 5F6A2F521CC09B9A00EF50C4 /* DeserializableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeserializableTests.swift; sourceTree = ""; }; 84 | 5F8F88221CA5F32E00EF50C4 /* DictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryTests.swift; sourceTree = ""; }; 85 | 5F8F88241CA5F33500EF50C4 /* EnumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnumTests.swift; sourceTree = ""; }; 86 | 5F928D981C0D469F00EF50C4 /* JSONHelper-tvOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JSONHelper-tvOS.h"; sourceTree = ""; }; 87 | 5F928D9A1C0D469F00EF50C4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 88 | 5FAD07641A70F2FC00C4D09E /* JSONHelper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSONHelper.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 89 | 5FAD07681A70F2FC00C4D09E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 90 | 5FAD07691A70F2FC00C4D09E /* JSONHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONHelper.h; sourceTree = ""; }; 91 | 5FAD076F1A70F2FC00C4D09E /* JSONHelperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSONHelperTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 92 | 5FAD07761A70F2FC00C4D09E /* JSONHelperTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = JSONHelperTests.swift; sourceTree = ""; tabWidth = 2; }; 93 | 5FAD07841A70F31300C4D09E /* JSONHelperExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSONHelperExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 94 | 5FAD07871A70F31300C4D09E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 95 | 5FAD07881A70F31300C4D09E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 96 | 5FAD078A1A70F31300C4D09E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 97 | 5FAD078D1A70F31300C4D09E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 98 | 5FAD078F1A70F31300C4D09E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 99 | 5FAD07921A70F31300C4D09E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 100 | 5FAD079D1A70F31300C4D09E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 101 | 5FAD079E1A70F31300C4D09E /* JSONHelperExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONHelperExampleTests.swift; sourceTree = ""; }; 102 | 5FB9D4DF1B38007C00EF50C4 /* StringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = ""; }; 103 | 5FC1A4861B1CFFB500EF50C4 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = String.swift; path = Extensions/String.swift; sourceTree = ""; }; 104 | 5FC1A4881B1D024500EF50C4 /* Int.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Int.swift; path = Extensions/Int.swift; sourceTree = ""; }; 105 | 5FC1A48D1B1D057B00EF50C4 /* Bool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Bool.swift; path = Extensions/Bool.swift; sourceTree = ""; }; 106 | 5FC1A48F1B1D082500EF50C4 /* Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Date.swift; path = Extensions/Date.swift; sourceTree = ""; }; 107 | 5FC1A4931B1D1D8B00EF50C4 /* URL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = URL.swift; path = Extensions/URL.swift; sourceTree = ""; }; 108 | 5FD3A09F1CA5F5C300EF50C4 /* ArrayTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayTests.swift; sourceTree = ""; }; 109 | /* End PBXFileReference section */ 110 | 111 | /* Begin PBXFrameworksBuildPhase section */ 112 | 5FAD07601A70F2FC00C4D09E /* Frameworks */ = { 113 | isa = PBXFrameworksBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | 5FAD076C1A70F2FC00C4D09E /* Frameworks */ = { 120 | isa = PBXFrameworksBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | 5FAD07701A70F2FC00C4D09E /* JSONHelper.framework in Frameworks */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | 5FAD07811A70F31300C4D09E /* Frameworks */ = { 128 | isa = PBXFrameworksBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXFrameworksBuildPhase section */ 135 | 136 | /* Begin PBXGroup section */ 137 | 5F0E6F971ACDE0BF00D92679 /* Mac */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 5F0E6F961ACDE06400D92679 /* Info.plist */, 141 | ); 142 | path = Mac; 143 | sourceTree = ""; 144 | }; 145 | 5F0E6F981ACDE0C400D92679 /* iOS */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 5FAD07681A70F2FC00C4D09E /* Info.plist */, 149 | ); 150 | path = iOS; 151 | sourceTree = ""; 152 | }; 153 | 5F133DA01C3840A200EF50C4 /* Support */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 5F133DA11C3840BB00EF50C4 /* JSONAPI.swift */, 157 | ); 158 | name = Support; 159 | sourceTree = ""; 160 | }; 161 | 5F6A2F511CC09B6000EF50C4 /* Extension Tests */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 5F024AE21B412BA900EF50C4 /* BoolTests.swift */, 165 | 5F024AE01B4127C900EF50C4 /* IntTests.swift */, 166 | 5F31FF7B1C53497600EF50C4 /* FloatTests.swift */, 167 | 5F31FF791C53496B00EF50C4 /* DoubleTests.swift */, 168 | 5F31FF7D1C53499000EF50C4 /* DecimalTests.swift */, 169 | 5FB9D4DF1B38007C00EF50C4 /* StringTests.swift */, 170 | 5F31FF6B1C533F1600EF50C4 /* ColorTests.swift */, 171 | 5F31FF551C5339B900EF50C4 /* DateTests.swift */, 172 | 5F31FF571C5339CE00EF50C4 /* URLTests.swift */, 173 | ); 174 | name = "Extension Tests"; 175 | sourceTree = ""; 176 | }; 177 | 5F6A2F541CC09BB500EF50C4 /* Support Tests */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | ); 181 | name = "Support Tests"; 182 | sourceTree = ""; 183 | }; 184 | 5F928D9F1C0D478800EF50C4 /* tvOS */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | 5F928D9A1C0D469F00EF50C4 /* Info.plist */, 188 | 5F928D981C0D469F00EF50C4 /* JSONHelper-tvOS.h */, 189 | ); 190 | path = tvOS; 191 | sourceTree = ""; 192 | }; 193 | 5FAD075A1A70F2FC00C4D09E = { 194 | isa = PBXGroup; 195 | children = ( 196 | 5FAD07661A70F2FC00C4D09E /* JSONHelper */, 197 | 5FAD07731A70F2FC00C4D09E /* JSONHelperTests */, 198 | 5FAD07851A70F31300C4D09E /* JSONHelperExample */, 199 | 5FAD079B1A70F31300C4D09E /* JSONHelperExampleTests */, 200 | 5FAD07651A70F2FC00C4D09E /* Products */, 201 | ); 202 | sourceTree = ""; 203 | }; 204 | 5FAD07651A70F2FC00C4D09E /* Products */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 5FAD07641A70F2FC00C4D09E /* JSONHelper.framework */, 208 | 5FAD076F1A70F2FC00C4D09E /* JSONHelperTests.xctest */, 209 | 5FAD07841A70F31300C4D09E /* JSONHelperExample.app */, 210 | ); 211 | name = Products; 212 | sourceTree = ""; 213 | }; 214 | 5FAD07661A70F2FC00C4D09E /* JSONHelper */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | 5FAD07691A70F2FC00C4D09E /* JSONHelper.h */, 218 | 5F6A2F491CC0116D00EF50C4 /* JSONHelper.swift */, 219 | 5F31FF5B1C533AD400EF50C4 /* Conversion.swift */, 220 | 5F31FF5D1C533AE000EF50C4 /* Deserialization.swift */, 221 | 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */, 222 | 5FC1A4851B1CFBE500EF50C4 /* Extensions */, 223 | 5F133DA01C3840A200EF50C4 /* Support */, 224 | 5FAD07671A70F2FC00C4D09E /* Supporting Files */, 225 | ); 226 | path = JSONHelper; 227 | sourceTree = ""; 228 | }; 229 | 5FAD07671A70F2FC00C4D09E /* Supporting Files */ = { 230 | isa = PBXGroup; 231 | children = ( 232 | 5F0E6F971ACDE0BF00D92679 /* Mac */, 233 | 5F0E6F981ACDE0C400D92679 /* iOS */, 234 | 5F928D9F1C0D478800EF50C4 /* tvOS */, 235 | ); 236 | path = "Supporting Files"; 237 | sourceTree = ""; 238 | }; 239 | 5FAD07731A70F2FC00C4D09E /* JSONHelperTests */ = { 240 | isa = PBXGroup; 241 | children = ( 242 | 5FAD07761A70F2FC00C4D09E /* JSONHelperTests.swift */, 243 | 5F6A2F511CC09B6000EF50C4 /* Extension Tests */, 244 | 5F8F88241CA5F33500EF50C4 /* EnumTests.swift */, 245 | 5F6A2F521CC09B9A00EF50C4 /* DeserializableTests.swift */, 246 | 5FD3A09F1CA5F5C300EF50C4 /* ArrayTests.swift */, 247 | 5F8F88221CA5F32E00EF50C4 /* DictionaryTests.swift */, 248 | 5F6A2F541CC09BB500EF50C4 /* Support Tests */, 249 | ); 250 | path = JSONHelperTests; 251 | sourceTree = ""; 252 | }; 253 | 5FAD07851A70F31300C4D09E /* JSONHelperExample */ = { 254 | isa = PBXGroup; 255 | children = ( 256 | 5FAD07861A70F31300C4D09E /* Supporting Files */, 257 | 5FAD07881A70F31300C4D09E /* AppDelegate.swift */, 258 | 5FAD078F1A70F31300C4D09E /* Images.xcassets */, 259 | 5FAD07911A70F31300C4D09E /* LaunchScreen.xib */, 260 | 5FAD078C1A70F31300C4D09E /* Main.storyboard */, 261 | 5FAD078A1A70F31300C4D09E /* ViewController.swift */, 262 | ); 263 | path = JSONHelperExample; 264 | sourceTree = ""; 265 | }; 266 | 5FAD07861A70F31300C4D09E /* Supporting Files */ = { 267 | isa = PBXGroup; 268 | children = ( 269 | 5FAD07871A70F31300C4D09E /* Info.plist */, 270 | ); 271 | path = "Supporting Files"; 272 | sourceTree = ""; 273 | }; 274 | 5FAD079B1A70F31300C4D09E /* JSONHelperExampleTests */ = { 275 | isa = PBXGroup; 276 | children = ( 277 | 5FAD079C1A70F31300C4D09E /* Supporting Files */, 278 | 5FAD079E1A70F31300C4D09E /* JSONHelperExampleTests.swift */, 279 | ); 280 | path = JSONHelperExampleTests; 281 | sourceTree = ""; 282 | }; 283 | 5FAD079C1A70F31300C4D09E /* Supporting Files */ = { 284 | isa = PBXGroup; 285 | children = ( 286 | 5FAD079D1A70F31300C4D09E /* Info.plist */, 287 | ); 288 | path = "Supporting Files"; 289 | sourceTree = ""; 290 | }; 291 | 5FC1A4851B1CFBE500EF50C4 /* Extensions */ = { 292 | isa = PBXGroup; 293 | children = ( 294 | 5FC1A48D1B1D057B00EF50C4 /* Bool.swift */, 295 | 5FC1A4881B1D024500EF50C4 /* Int.swift */, 296 | 5F31FF751C53490B00EF50C4 /* Float.swift */, 297 | 5F31FF711C5348FE00EF50C4 /* Double.swift */, 298 | 5F31FF6D1C5348F000EF50C4 /* DecimalNumber.swift */, 299 | 5FC1A4861B1CFFB500EF50C4 /* String.swift */, 300 | 5F31FF5F1C533E9900EF50C4 /* Color.swift */, 301 | 5FC1A48F1B1D082500EF50C4 /* Date.swift */, 302 | 5FC1A4931B1D1D8B00EF50C4 /* URL.swift */, 303 | ); 304 | name = Extensions; 305 | sourceTree = ""; 306 | }; 307 | /* End PBXGroup section */ 308 | 309 | /* Begin PBXHeadersBuildPhase section */ 310 | 5FAD07611A70F2FC00C4D09E /* Headers */ = { 311 | isa = PBXHeadersBuildPhase; 312 | buildActionMask = 2147483647; 313 | files = ( 314 | 5FAD076A1A70F2FC00C4D09E /* JSONHelper.h in Headers */, 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | }; 318 | /* End PBXHeadersBuildPhase section */ 319 | 320 | /* Begin PBXNativeTarget section */ 321 | 5FAD07631A70F2FC00C4D09E /* JSONHelper */ = { 322 | isa = PBXNativeTarget; 323 | buildConfigurationList = 5FAD077A1A70F2FC00C4D09E /* Build configuration list for PBXNativeTarget "JSONHelper" */; 324 | buildPhases = ( 325 | 5FAD075F1A70F2FC00C4D09E /* Sources */, 326 | 5FAD07601A70F2FC00C4D09E /* Frameworks */, 327 | 5FAD07611A70F2FC00C4D09E /* Headers */, 328 | 5FAD07621A70F2FC00C4D09E /* Resources */, 329 | ); 330 | buildRules = ( 331 | ); 332 | dependencies = ( 333 | ); 334 | name = JSONHelper; 335 | productName = JSONHelper; 336 | productReference = 5FAD07641A70F2FC00C4D09E /* JSONHelper.framework */; 337 | productType = "com.apple.product-type.framework"; 338 | }; 339 | 5FAD076E1A70F2FC00C4D09E /* JSONHelperTests */ = { 340 | isa = PBXNativeTarget; 341 | buildConfigurationList = 5FAD077D1A70F2FC00C4D09E /* Build configuration list for PBXNativeTarget "JSONHelperTests" */; 342 | buildPhases = ( 343 | 5FAD076B1A70F2FC00C4D09E /* Sources */, 344 | 5FAD076C1A70F2FC00C4D09E /* Frameworks */, 345 | 5FAD076D1A70F2FC00C4D09E /* Resources */, 346 | ); 347 | buildRules = ( 348 | ); 349 | dependencies = ( 350 | 5FAD07721A70F2FC00C4D09E /* PBXTargetDependency */, 351 | ); 352 | name = JSONHelperTests; 353 | productName = JSONHelperTests; 354 | productReference = 5FAD076F1A70F2FC00C4D09E /* JSONHelperTests.xctest */; 355 | productType = "com.apple.product-type.bundle.unit-test"; 356 | }; 357 | 5FAD07831A70F31300C4D09E /* JSONHelperExample */ = { 358 | isa = PBXNativeTarget; 359 | buildConfigurationList = 5FAD07A01A70F31300C4D09E /* Build configuration list for PBXNativeTarget "JSONHelperExample" */; 360 | buildPhases = ( 361 | 5FAD07801A70F31300C4D09E /* Sources */, 362 | 5FAD07811A70F31300C4D09E /* Frameworks */, 363 | 5FAD07821A70F31300C4D09E /* Resources */, 364 | ); 365 | buildRules = ( 366 | ); 367 | dependencies = ( 368 | 5F0E6F951ACDD94E00D92679 /* PBXTargetDependency */, 369 | ); 370 | name = JSONHelperExample; 371 | productName = JSONHelperExample; 372 | productReference = 5FAD07841A70F31300C4D09E /* JSONHelperExample.app */; 373 | productType = "com.apple.product-type.application"; 374 | }; 375 | /* End PBXNativeTarget section */ 376 | 377 | /* Begin PBXProject section */ 378 | 5FAD075B1A70F2FC00C4D09E /* Project object */ = { 379 | isa = PBXProject; 380 | attributes = { 381 | LastUpgradeCheck = 0830; 382 | ORGANIZATIONNAME = "Baris Sencan"; 383 | TargetAttributes = { 384 | 5FAD07631A70F2FC00C4D09E = { 385 | CreatedOnToolsVersion = 6.1.1; 386 | LastSwiftMigration = 1010; 387 | ProvisioningStyle = Automatic; 388 | }; 389 | 5FAD076E1A70F2FC00C4D09E = { 390 | CreatedOnToolsVersion = 6.1.1; 391 | DevelopmentTeam = LCA97TAP6U; 392 | LastSwiftMigration = 1010; 393 | ProvisioningStyle = Automatic; 394 | }; 395 | 5FAD07831A70F31300C4D09E = { 396 | CreatedOnToolsVersion = 6.1.1; 397 | DevelopmentTeam = LCA97TAP6U; 398 | }; 399 | }; 400 | }; 401 | buildConfigurationList = 5FAD075E1A70F2FC00C4D09E /* Build configuration list for PBXProject "JSONHelper" */; 402 | compatibilityVersion = "Xcode 3.2"; 403 | developmentRegion = English; 404 | hasScannedForEncodings = 0; 405 | knownRegions = ( 406 | en, 407 | Base, 408 | ); 409 | mainGroup = 5FAD075A1A70F2FC00C4D09E; 410 | productRefGroup = 5FAD07651A70F2FC00C4D09E /* Products */; 411 | projectDirPath = ""; 412 | projectRoot = ""; 413 | targets = ( 414 | 5FAD07631A70F2FC00C4D09E /* JSONHelper */, 415 | 5FAD076E1A70F2FC00C4D09E /* JSONHelperTests */, 416 | 5FAD07831A70F31300C4D09E /* JSONHelperExample */, 417 | ); 418 | }; 419 | /* End PBXProject section */ 420 | 421 | /* Begin PBXResourcesBuildPhase section */ 422 | 5FAD07621A70F2FC00C4D09E /* Resources */ = { 423 | isa = PBXResourcesBuildPhase; 424 | buildActionMask = 2147483647; 425 | files = ( 426 | ); 427 | runOnlyForDeploymentPostprocessing = 0; 428 | }; 429 | 5FAD076D1A70F2FC00C4D09E /* Resources */ = { 430 | isa = PBXResourcesBuildPhase; 431 | buildActionMask = 2147483647; 432 | files = ( 433 | ); 434 | runOnlyForDeploymentPostprocessing = 0; 435 | }; 436 | 5FAD07821A70F31300C4D09E /* Resources */ = { 437 | isa = PBXResourcesBuildPhase; 438 | buildActionMask = 2147483647; 439 | files = ( 440 | 5FAD078E1A70F31300C4D09E /* Main.storyboard in Resources */, 441 | 5FAD07931A70F31300C4D09E /* LaunchScreen.xib in Resources */, 442 | 5FAD07901A70F31300C4D09E /* Images.xcassets in Resources */, 443 | ); 444 | runOnlyForDeploymentPostprocessing = 0; 445 | }; 446 | /* End PBXResourcesBuildPhase section */ 447 | 448 | /* Begin PBXSourcesBuildPhase section */ 449 | 5FAD075F1A70F2FC00C4D09E /* Sources */ = { 450 | isa = PBXSourcesBuildPhase; 451 | buildActionMask = 2147483647; 452 | files = ( 453 | 5FC1A4941B1D1D8B00EF50C4 /* URL.swift in Sources */, 454 | 5F31FF6E1C5348F000EF50C4 /* DecimalNumber.swift in Sources */, 455 | 5F6A2F4E1CC096DA00EF50C4 /* Serialization.swift in Sources */, 456 | 5FC1A4891B1D024500EF50C4 /* Int.swift in Sources */, 457 | 5FC1A48E1B1D057B00EF50C4 /* Bool.swift in Sources */, 458 | 5F31FF601C533E9900EF50C4 /* Color.swift in Sources */, 459 | 5FC1A4871B1CFFB500EF50C4 /* String.swift in Sources */, 460 | 5F31FF5E1C533AE000EF50C4 /* Deserialization.swift in Sources */, 461 | 5F133DA21C3840BB00EF50C4 /* JSONAPI.swift in Sources */, 462 | 5F6A2F4A1CC0116D00EF50C4 /* JSONHelper.swift in Sources */, 463 | 5FC1A4901B1D082500EF50C4 /* Date.swift in Sources */, 464 | 5F31FF761C53490B00EF50C4 /* Float.swift in Sources */, 465 | 5F31FF5C1C533AD400EF50C4 /* Conversion.swift in Sources */, 466 | 5F31FF721C5348FE00EF50C4 /* Double.swift in Sources */, 467 | ); 468 | runOnlyForDeploymentPostprocessing = 0; 469 | }; 470 | 5FAD076B1A70F2FC00C4D09E /* Sources */ = { 471 | isa = PBXSourcesBuildPhase; 472 | buildActionMask = 2147483647; 473 | files = ( 474 | 5F024AE11B4127C900EF50C4 /* IntTests.swift in Sources */, 475 | 5F6A2F531CC09B9A00EF50C4 /* DeserializableTests.swift in Sources */, 476 | 5F024AE31B412BA900EF50C4 /* BoolTests.swift in Sources */, 477 | 5F31FF7A1C53496B00EF50C4 /* DoubleTests.swift in Sources */, 478 | 5F31FF7E1C53499000EF50C4 /* DecimalTests.swift in Sources */, 479 | 5F31FF581C5339CE00EF50C4 /* URLTests.swift in Sources */, 480 | 5FB9D4E01B38007C00EF50C4 /* StringTests.swift in Sources */, 481 | 5FAD07771A70F2FC00C4D09E /* JSONHelperTests.swift in Sources */, 482 | 5F31FF7C1C53497600EF50C4 /* FloatTests.swift in Sources */, 483 | 5F8F88231CA5F32E00EF50C4 /* DictionaryTests.swift in Sources */, 484 | 5F31FF6C1C533F1600EF50C4 /* ColorTests.swift in Sources */, 485 | 5F8F88251CA5F33500EF50C4 /* EnumTests.swift in Sources */, 486 | 5FD3A0A01CA5F5C300EF50C4 /* ArrayTests.swift in Sources */, 487 | 5F31FF561C5339B900EF50C4 /* DateTests.swift in Sources */, 488 | ); 489 | runOnlyForDeploymentPostprocessing = 0; 490 | }; 491 | 5FAD07801A70F31300C4D09E /* Sources */ = { 492 | isa = PBXSourcesBuildPhase; 493 | buildActionMask = 2147483647; 494 | files = ( 495 | 5FAD078B1A70F31300C4D09E /* ViewController.swift in Sources */, 496 | 5FAD07891A70F31300C4D09E /* AppDelegate.swift in Sources */, 497 | ); 498 | runOnlyForDeploymentPostprocessing = 0; 499 | }; 500 | /* End PBXSourcesBuildPhase section */ 501 | 502 | /* Begin PBXTargetDependency section */ 503 | 5F0E6F951ACDD94E00D92679 /* PBXTargetDependency */ = { 504 | isa = PBXTargetDependency; 505 | target = 5FAD07631A70F2FC00C4D09E /* JSONHelper */; 506 | targetProxy = 5F0E6F941ACDD94E00D92679 /* PBXContainerItemProxy */; 507 | }; 508 | 5FAD07721A70F2FC00C4D09E /* PBXTargetDependency */ = { 509 | isa = PBXTargetDependency; 510 | target = 5FAD07631A70F2FC00C4D09E /* JSONHelper */; 511 | targetProxy = 5FAD07711A70F2FC00C4D09E /* PBXContainerItemProxy */; 512 | }; 513 | /* End PBXTargetDependency section */ 514 | 515 | /* Begin PBXVariantGroup section */ 516 | 5FAD078C1A70F31300C4D09E /* Main.storyboard */ = { 517 | isa = PBXVariantGroup; 518 | children = ( 519 | 5FAD078D1A70F31300C4D09E /* Base */, 520 | ); 521 | name = Main.storyboard; 522 | path = .; 523 | sourceTree = ""; 524 | }; 525 | 5FAD07911A70F31300C4D09E /* LaunchScreen.xib */ = { 526 | isa = PBXVariantGroup; 527 | children = ( 528 | 5FAD07921A70F31300C4D09E /* Base */, 529 | ); 530 | name = LaunchScreen.xib; 531 | path = .; 532 | sourceTree = ""; 533 | }; 534 | /* End PBXVariantGroup section */ 535 | 536 | /* Begin XCBuildConfiguration section */ 537 | 5FAD07781A70F2FC00C4D09E /* Debug */ = { 538 | isa = XCBuildConfiguration; 539 | buildSettings = { 540 | ALWAYS_SEARCH_USER_PATHS = NO; 541 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 542 | CLANG_CXX_LIBRARY = "libc++"; 543 | CLANG_ENABLE_MODULES = YES; 544 | CLANG_ENABLE_OBJC_ARC = YES; 545 | CLANG_WARN_BOOL_CONVERSION = YES; 546 | CLANG_WARN_CONSTANT_CONVERSION = YES; 547 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 548 | CLANG_WARN_EMPTY_BODY = YES; 549 | CLANG_WARN_ENUM_CONVERSION = YES; 550 | CLANG_WARN_INFINITE_RECURSION = YES; 551 | CLANG_WARN_INT_CONVERSION = YES; 552 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 553 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 554 | CLANG_WARN_UNREACHABLE_CODE = YES; 555 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 556 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 557 | COPY_PHASE_STRIP = NO; 558 | CURRENT_PROJECT_VERSION = 1; 559 | ENABLE_STRICT_OBJC_MSGSEND = YES; 560 | ENABLE_TESTABILITY = YES; 561 | GCC_C_LANGUAGE_STANDARD = gnu99; 562 | GCC_DYNAMIC_NO_PIC = NO; 563 | GCC_NO_COMMON_BLOCKS = YES; 564 | GCC_OPTIMIZATION_LEVEL = 0; 565 | GCC_PREPROCESSOR_DEFINITIONS = ( 566 | "DEBUG=1", 567 | "$(inherited)", 568 | ); 569 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 570 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 571 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 572 | GCC_WARN_UNDECLARED_SELECTOR = YES; 573 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 574 | GCC_WARN_UNUSED_FUNCTION = YES; 575 | GCC_WARN_UNUSED_VARIABLE = YES; 576 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 577 | MTL_ENABLE_DEBUG_INFO = YES; 578 | ONLY_ACTIVE_ARCH = YES; 579 | SDKROOT = iphoneos; 580 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 581 | TARGETED_DEVICE_FAMILY = "1,2,3"; 582 | VERSIONING_SYSTEM = "apple-generic"; 583 | VERSION_INFO_PREFIX = ""; 584 | }; 585 | name = Debug; 586 | }; 587 | 5FAD07791A70F2FC00C4D09E /* Release */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | ALWAYS_SEARCH_USER_PATHS = NO; 591 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 592 | CLANG_CXX_LIBRARY = "libc++"; 593 | CLANG_ENABLE_MODULES = YES; 594 | CLANG_ENABLE_OBJC_ARC = YES; 595 | CLANG_WARN_BOOL_CONVERSION = YES; 596 | CLANG_WARN_CONSTANT_CONVERSION = YES; 597 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 598 | CLANG_WARN_EMPTY_BODY = YES; 599 | CLANG_WARN_ENUM_CONVERSION = YES; 600 | CLANG_WARN_INFINITE_RECURSION = YES; 601 | CLANG_WARN_INT_CONVERSION = YES; 602 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 603 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 604 | CLANG_WARN_UNREACHABLE_CODE = YES; 605 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 606 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 607 | COPY_PHASE_STRIP = YES; 608 | CURRENT_PROJECT_VERSION = 1; 609 | ENABLE_NS_ASSERTIONS = NO; 610 | ENABLE_STRICT_OBJC_MSGSEND = YES; 611 | GCC_C_LANGUAGE_STANDARD = gnu99; 612 | GCC_NO_COMMON_BLOCKS = YES; 613 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 614 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 615 | GCC_WARN_UNDECLARED_SELECTOR = YES; 616 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 617 | GCC_WARN_UNUSED_FUNCTION = YES; 618 | GCC_WARN_UNUSED_VARIABLE = YES; 619 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 620 | MTL_ENABLE_DEBUG_INFO = NO; 621 | SDKROOT = iphoneos; 622 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 623 | TARGETED_DEVICE_FAMILY = "1,2,3"; 624 | VALIDATE_PRODUCT = YES; 625 | VERSIONING_SYSTEM = "apple-generic"; 626 | VERSION_INFO_PREFIX = ""; 627 | }; 628 | name = Release; 629 | }; 630 | 5FAD077B1A70F2FC00C4D09E /* Debug */ = { 631 | isa = XCBuildConfiguration; 632 | buildSettings = { 633 | CLANG_ENABLE_MODULES = YES; 634 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 635 | DEFINES_MODULE = YES; 636 | DEVELOPMENT_TEAM = ""; 637 | DYLIB_COMPATIBILITY_VERSION = 1; 638 | DYLIB_CURRENT_VERSION = 1; 639 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 640 | INFOPLIST_FILE = "JSONHelper/Supporting Files/iOS/Info.plist"; 641 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 642 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 643 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 644 | MACOSX_DEPLOYMENT_TARGET = 10.9; 645 | PRODUCT_BUNDLE_IDENTIFIER = com.bsencan.JSONHelper; 646 | PRODUCT_NAME = JSONHelper; 647 | PROVISIONING_PROFILE_SPECIFIER = ""; 648 | SKIP_INSTALL = YES; 649 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator"; 650 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 651 | SWIFT_VERSION = 4.2; 652 | TVOS_DEPLOYMENT_TARGET = 9.0; 653 | }; 654 | name = Debug; 655 | }; 656 | 5FAD077C1A70F2FC00C4D09E /* Release */ = { 657 | isa = XCBuildConfiguration; 658 | buildSettings = { 659 | CLANG_ENABLE_MODULES = YES; 660 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 661 | DEFINES_MODULE = YES; 662 | DEVELOPMENT_TEAM = ""; 663 | DYLIB_COMPATIBILITY_VERSION = 1; 664 | DYLIB_CURRENT_VERSION = 1; 665 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 666 | INFOPLIST_FILE = "JSONHelper/Supporting Files/iOS/Info.plist"; 667 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 668 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 669 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 670 | MACOSX_DEPLOYMENT_TARGET = 10.9; 671 | PRODUCT_BUNDLE_IDENTIFIER = com.bsencan.JSONHelper; 672 | PRODUCT_NAME = JSONHelper; 673 | PROVISIONING_PROFILE_SPECIFIER = ""; 674 | SKIP_INSTALL = YES; 675 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator"; 676 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 677 | SWIFT_VERSION = 4.2; 678 | TVOS_DEPLOYMENT_TARGET = 9.0; 679 | }; 680 | name = Release; 681 | }; 682 | 5FAD077E1A70F2FC00C4D09E /* Debug */ = { 683 | isa = XCBuildConfiguration; 684 | buildSettings = { 685 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 686 | DEVELOPMENT_TEAM = LCA97TAP6U; 687 | FRAMEWORK_SEARCH_PATHS = ( 688 | "$(SDKROOT)/Developer/Library/Frameworks", 689 | "$(inherited)", 690 | ); 691 | INFOPLIST_FILE = "JSONHelperTests/Supporting Files/Info.plist"; 692 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 693 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 694 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 695 | PRODUCT_NAME = "$(TARGET_NAME)"; 696 | PROVISIONING_PROFILE_SPECIFIER = ""; 697 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator"; 698 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 699 | SWIFT_VERSION = 4.2; 700 | }; 701 | name = Debug; 702 | }; 703 | 5FAD077F1A70F2FC00C4D09E /* Release */ = { 704 | isa = XCBuildConfiguration; 705 | buildSettings = { 706 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 707 | DEVELOPMENT_TEAM = LCA97TAP6U; 708 | FRAMEWORK_SEARCH_PATHS = ( 709 | "$(SDKROOT)/Developer/Library/Frameworks", 710 | "$(inherited)", 711 | ); 712 | INFOPLIST_FILE = "JSONHelperTests/Supporting Files/Info.plist"; 713 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 714 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 715 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 716 | PRODUCT_NAME = "$(TARGET_NAME)"; 717 | PROVISIONING_PROFILE_SPECIFIER = ""; 718 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator"; 719 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 720 | SWIFT_VERSION = 4.2; 721 | }; 722 | name = Release; 723 | }; 724 | 5FAD07A11A70F31300C4D09E /* Debug */ = { 725 | isa = XCBuildConfiguration; 726 | buildSettings = { 727 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 728 | DEVELOPMENT_TEAM = LCA97TAP6U; 729 | GCC_PREPROCESSOR_DEFINITIONS = ( 730 | "DEBUG=1", 731 | "$(inherited)", 732 | ); 733 | INFOPLIST_FILE = "JSONHelperExample/Supporting Files/Info.plist"; 734 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 735 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 736 | PRODUCT_NAME = "$(TARGET_NAME)"; 737 | }; 738 | name = Debug; 739 | }; 740 | 5FAD07A21A70F31300C4D09E /* Release */ = { 741 | isa = XCBuildConfiguration; 742 | buildSettings = { 743 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 744 | DEVELOPMENT_TEAM = LCA97TAP6U; 745 | INFOPLIST_FILE = "JSONHelperExample/Supporting Files/Info.plist"; 746 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 747 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 748 | PRODUCT_NAME = "$(TARGET_NAME)"; 749 | }; 750 | name = Release; 751 | }; 752 | /* End XCBuildConfiguration section */ 753 | 754 | /* Begin XCConfigurationList section */ 755 | 5FAD075E1A70F2FC00C4D09E /* Build configuration list for PBXProject "JSONHelper" */ = { 756 | isa = XCConfigurationList; 757 | buildConfigurations = ( 758 | 5FAD07781A70F2FC00C4D09E /* Debug */, 759 | 5FAD07791A70F2FC00C4D09E /* Release */, 760 | ); 761 | defaultConfigurationIsVisible = 0; 762 | defaultConfigurationName = Release; 763 | }; 764 | 5FAD077A1A70F2FC00C4D09E /* Build configuration list for PBXNativeTarget "JSONHelper" */ = { 765 | isa = XCConfigurationList; 766 | buildConfigurations = ( 767 | 5FAD077B1A70F2FC00C4D09E /* Debug */, 768 | 5FAD077C1A70F2FC00C4D09E /* Release */, 769 | ); 770 | defaultConfigurationIsVisible = 0; 771 | defaultConfigurationName = Release; 772 | }; 773 | 5FAD077D1A70F2FC00C4D09E /* Build configuration list for PBXNativeTarget "JSONHelperTests" */ = { 774 | isa = XCConfigurationList; 775 | buildConfigurations = ( 776 | 5FAD077E1A70F2FC00C4D09E /* Debug */, 777 | 5FAD077F1A70F2FC00C4D09E /* Release */, 778 | ); 779 | defaultConfigurationIsVisible = 0; 780 | defaultConfigurationName = Release; 781 | }; 782 | 5FAD07A01A70F31300C4D09E /* Build configuration list for PBXNativeTarget "JSONHelperExample" */ = { 783 | isa = XCConfigurationList; 784 | buildConfigurations = ( 785 | 5FAD07A11A70F31300C4D09E /* Debug */, 786 | 5FAD07A21A70F31300C4D09E /* Release */, 787 | ); 788 | defaultConfigurationIsVisible = 0; 789 | defaultConfigurationName = Release; 790 | }; 791 | /* End XCConfigurationList section */ 792 | }; 793 | rootObject = 5FAD075B1A70F2FC00C4D09E /* Project object */; 794 | } 795 | -------------------------------------------------------------------------------- /JSONHelper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JSONHelper.xcodeproj/project.xcworkspace/xcshareddata/JSONHelper.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 1241D256-F695-4133-915E-09E8E66CFE38 9 | IDESourceControlProjectName 10 | JSONHelper 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 9540366943750F418CA1A28462EA7F786EC07683 14 | github.com:isair/JSONHelper.git 15 | 16 | IDESourceControlProjectPath 17 | JSONHelper.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 9540366943750F418CA1A28462EA7F786EC07683 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:isair/JSONHelper.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 9540366943750F418CA1A28462EA7F786EC07683 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 9540366943750F418CA1A28462EA7F786EC07683 36 | IDESourceControlWCCName 37 | JSONHelper 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /JSONHelper.xcodeproj/xcshareddata/xcschemes/JSONHelper.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /JSONHelper.xcodeproj/xcshareddata/xcschemes/JSONHelperExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /JSONHelper/Conversion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | /// Operator for use in right hand side to left hand side conversion. 8 | infix operator <-- : convert 9 | precedencegroup convert 10 | { 11 | associativity: right 12 | } 13 | 14 | /// Thrown when a conversion operation fails. 15 | public enum ConversionError: Error { 16 | 17 | /// TODOC 18 | case unsupportedType 19 | 20 | /// TODOC 21 | case invalidValue 22 | } 23 | 24 | /// An object that can attempt to convert values of unknown types to its own type. 25 | public protocol Convertible { 26 | 27 | /// TODOC 28 | static func convert(fromValue value: T?) throws -> Self? 29 | } 30 | 31 | // MARK: - Basic Conversion 32 | 33 | @discardableResult public func <-- (lhs: inout T?, rhs: U?) -> T? { 34 | if !(lhs is NSNull) { 35 | lhs = JSONHelper.convertToNilIfNull(rhs) as? T 36 | } else { 37 | lhs = rhs as? T 38 | } 39 | return lhs 40 | } 41 | 42 | @discardableResult public func <-- (lhs: inout T, rhs: U?) -> T { 43 | var newValue: T? 44 | newValue <-- rhs 45 | lhs = newValue ?? lhs 46 | return lhs 47 | } 48 | 49 | @discardableResult public func <-- (lhs: inout C?, rhs: T?) -> C? { 50 | lhs = nil 51 | 52 | do { 53 | lhs = try C.convert(fromValue: JSONHelper.convertToNilIfNull(rhs)) 54 | } catch ConversionError.invalidValue { 55 | #if DEBUG 56 | print("Invalid value \(rhs.debugDescription) for supported type.") 57 | #endif 58 | } catch ConversionError.unsupportedType { 59 | #if DEBUG 60 | print("Unsupported type.") 61 | #endif 62 | } catch {} 63 | 64 | return lhs 65 | } 66 | 67 | @discardableResult public func <-- (lhs: inout C, rhs: T?) -> C { 68 | var newValue: C? 69 | newValue <-- rhs 70 | lhs = newValue ?? lhs 71 | return lhs 72 | } 73 | 74 | // MARK: - Array Conversion 75 | 76 | @discardableResult public func <-- (lhs: inout [C]?, rhs: [T]?) -> [C]? { 77 | guard let rhs = rhs else { 78 | lhs = nil 79 | return lhs 80 | } 81 | 82 | lhs = [C]() 83 | for element in rhs { 84 | var convertedElement: C? 85 | convertedElement <-- element 86 | 87 | if let convertedElement = convertedElement { 88 | lhs?.append(convertedElement) 89 | } 90 | } 91 | 92 | return lhs 93 | } 94 | 95 | @discardableResult public func <-- (lhs: inout [C], rhs: [T]?) -> [C] { 96 | var newValue: [C]? 97 | newValue <-- rhs 98 | lhs = newValue ?? lhs 99 | return lhs 100 | } 101 | 102 | @discardableResult public func <-- (lhs: inout [C]?, rhs: T?) -> [C]? { 103 | guard let rhs = rhs else { 104 | lhs = nil 105 | return lhs 106 | } 107 | 108 | if let elements = rhs as? NSArray as [AnyObject]? { 109 | return lhs <-- elements 110 | } 111 | 112 | return nil 113 | } 114 | 115 | @discardableResult public func <-- (lhs: inout [C], rhs: T?) -> [C] { 116 | var newValue: [C]? 117 | newValue <-- rhs 118 | lhs = newValue ?? lhs 119 | return lhs 120 | } 121 | 122 | // MARK: - Dictionary Conversion 123 | 124 | @discardableResult public func <-- (lhs: inout [T : C]?, rhs: [T : U]?) -> [T : C]? { 125 | guard let rhs = rhs else { 126 | lhs = nil 127 | return lhs 128 | } 129 | 130 | lhs = [T : C]() 131 | for (key, value) in rhs { 132 | var convertedValue: C? 133 | convertedValue <-- value 134 | if let convertedValue = convertedValue { 135 | lhs?[key] = convertedValue 136 | } 137 | } 138 | 139 | return lhs 140 | } 141 | 142 | @discardableResult public func <-- (lhs: inout [T : C], rhs: [T : U]?) -> [T : C] { 143 | var newValue: [T : C]? 144 | newValue <-- rhs 145 | lhs = newValue ?? lhs 146 | return lhs 147 | } 148 | 149 | @discardableResult public func <-- (lhs: inout [T : C]?, rhs: U?) -> [T : C]? { 150 | guard let rhs = rhs else { 151 | lhs = nil 152 | return lhs 153 | } 154 | 155 | if let elements = rhs as? NSDictionary as? [T : AnyObject] { 156 | return lhs <-- elements 157 | } 158 | 159 | return nil 160 | } 161 | 162 | @discardableResult public func <-- (lhs: inout [T : C], rhs: U?) -> [T : C] { 163 | var newValue: [T : C]? 164 | newValue <-- rhs 165 | lhs = newValue ?? lhs 166 | return lhs 167 | } 168 | 169 | // MARK: - Enum Conversion 170 | 171 | @discardableResult public func <-- (lhs: inout T?, rhs: U?) -> T? { 172 | var newValue: T? 173 | 174 | if let 175 | rawValue = rhs as? T.RawValue, 176 | let enumValue = T(rawValue: rawValue) { 177 | newValue = enumValue 178 | } 179 | lhs = newValue 180 | 181 | return lhs 182 | } 183 | 184 | @discardableResult public func <-- (lhs: inout T, rhs: U?) -> T { 185 | var newValue: T? 186 | newValue <-- rhs 187 | lhs = newValue ?? lhs 188 | return lhs 189 | } 190 | -------------------------------------------------------------------------------- /JSONHelper/Deserialization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | /// TODOC 8 | public protocol Deserializable { 9 | 10 | /// TODOC 11 | init(dictionary: [String : Any]) 12 | } 13 | 14 | // MARK: - Helper Methods 15 | 16 | private func dataStringToObject(_ dataString: String) -> AnyObject? { 17 | guard let data: Data = dataString.data(using: String.Encoding.utf8) else { return nil } 18 | var jsonObject: Any? 19 | do { 20 | jsonObject = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: 0)) 21 | } catch {} 22 | return jsonObject as AnyObject? 23 | } 24 | 25 | // MARK: - Basic Deserialization 26 | 27 | @discardableResult public func <-- (lhs: inout D?, rhs: T?) -> D? { 28 | let cleanedValue = JSONHelper.convertToNilIfNull(rhs) 29 | 30 | if let jsonObject = cleanedValue as? NSDictionary as? [String : AnyObject] { 31 | lhs = D(dictionary: jsonObject) 32 | } else if let string = cleanedValue as? String { 33 | lhs <-- dataStringToObject(string) 34 | } else { 35 | lhs = nil 36 | } 37 | 38 | return lhs 39 | } 40 | 41 | @discardableResult public func <-- (lhs: inout D, rhs: T?) -> D { 42 | var newValue: D? 43 | newValue <-- rhs 44 | lhs = newValue ?? lhs 45 | return lhs 46 | } 47 | 48 | // MARK: - Array Deserialization 49 | 50 | @discardableResult public func <-- (lhs: inout [D]?, rhs: [T]?) -> [D]? { 51 | guard let rhs = rhs else { return nil } 52 | 53 | lhs = [D]() 54 | for element in rhs { 55 | var convertedElement: D? 56 | convertedElement <-- element 57 | 58 | if let convertedElement = convertedElement { 59 | lhs?.append(convertedElement) 60 | } 61 | } 62 | 63 | return lhs 64 | } 65 | 66 | @discardableResult public func <-- (lhs: inout [D], rhs: [T]?) -> [D] { 67 | var newValue: [D]? 68 | newValue <-- rhs 69 | lhs = newValue ?? lhs 70 | return lhs 71 | } 72 | 73 | @discardableResult public func <-- (lhs: inout [D]?, rhs: T?) -> [D]? { 74 | guard let rhs = rhs else { return nil } 75 | 76 | if let elements = rhs as? NSArray as [AnyObject]? { 77 | return lhs <-- elements 78 | } 79 | 80 | return nil 81 | } 82 | 83 | @discardableResult public func <-- (lhs: inout [D], rhs: T?) -> [D] { 84 | var newValue: [D]? 85 | newValue <-- rhs 86 | lhs = newValue ?? lhs 87 | return lhs 88 | } 89 | 90 | // MARK: - Dictionary Deserialization 91 | 92 | @discardableResult public func <-- (lhs: inout [T : D]?, rhs: [T : U]?) -> [T : D]? { 93 | guard let rhs = rhs else { 94 | lhs = nil 95 | return lhs 96 | } 97 | 98 | lhs = [T : D]() 99 | for (key, value) in rhs { 100 | var convertedValue: D? 101 | convertedValue <-- value 102 | 103 | if let convertedValue = convertedValue { 104 | lhs?[key] = convertedValue 105 | } 106 | } 107 | 108 | return lhs 109 | } 110 | 111 | @discardableResult public func <-- (lhs: inout [T : D], rhs: [T : U]?) -> [T : D] { 112 | var newValue: [T : D]? 113 | newValue <-- rhs 114 | lhs = newValue ?? lhs 115 | return lhs 116 | } 117 | 118 | @discardableResult public func <-- (lhs: inout [T : D]?, rhs: U?) -> [T : D]? { 119 | guard let rhs = rhs else { 120 | lhs = nil 121 | return lhs 122 | } 123 | 124 | if let elements = rhs as? NSDictionary as? [T : AnyObject] { 125 | return lhs <-- elements 126 | } 127 | 128 | return nil 129 | } 130 | 131 | @discardableResult public func <-- (lhs: inout [T : D], rhs: U?) -> [T : D] { 132 | var newValue: [T : D]? 133 | newValue <-- rhs 134 | lhs = newValue ?? lhs 135 | return lhs 136 | } 137 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/Bool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension Bool: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> Bool? { 10 | guard let value = value else { return nil } 11 | 12 | if let boolValue = value as? Bool { 13 | return boolValue 14 | } else if let intValue = value as? Int { 15 | return intValue > 0 16 | } else if let stringValue = value as? String { 17 | switch stringValue.lowercased() { 18 | case "true", "t", "yes", "y": 19 | return true 20 | case "false", "f", "no", "n": 21 | return false 22 | default: 23 | throw ConversionError.invalidValue 24 | } 25 | } 26 | 27 | throw ConversionError.unsupportedType 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/Color.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | private struct ColorConversionHelper { 6 | 7 | fileprivate static func hexStringToRGBA(_ hexString: String) throws -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { 8 | var red = CGFloat(0) 9 | var green = CGFloat(0) 10 | var blue = CGFloat(0) 11 | var alpha = CGFloat(1) 12 | 13 | if hexString.hasPrefix("#") { 14 | let index = hexString.characters.index(hexString.startIndex, offsetBy: 1) 15 | let hex = hexString.substring(from: index) 16 | let scanner = Scanner(string: hex) 17 | var hexValue = CUnsignedLongLong(0) 18 | 19 | if scanner.scanHexInt64(&hexValue) { 20 | switch (hex.characters.count) { 21 | case 3: 22 | red = CGFloat((hexValue & 0xF00) >> 8) / 15.0 23 | green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0 24 | blue = CGFloat(hexValue & 0x00F) / 15.0 25 | case 4: 26 | red = CGFloat((hexValue & 0xF000) >> 12) / 15.0 27 | green = CGFloat((hexValue & 0x0F00) >> 8) / 15.0 28 | blue = CGFloat((hexValue & 0x00F0) >> 4) / 15.0 29 | alpha = CGFloat(hexValue & 0x000F) / 15.0 30 | case 6: 31 | red = CGFloat((hexValue & 0xFF0000) >> 16) / 255.0 32 | green = CGFloat((hexValue & 0x00FF00) >> 8) / 255.0 33 | blue = CGFloat(hexValue & 0x0000FF) / 255.0 34 | case 8: 35 | red = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0 36 | green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0 37 | blue = CGFloat((hexValue & 0x0000FF00) >> 8) / 255.0 38 | alpha = CGFloat(hexValue & 0x000000FF) / 255.0 39 | default: 40 | throw ConversionError.invalidValue 41 | } 42 | } 43 | } 44 | return (red: red, green: green, blue: blue, alpha: alpha) 45 | } 46 | } 47 | 48 | #if os(OSX) 49 | 50 | import AppKit 51 | 52 | extension NSColor: Convertible { 53 | 54 | public static func convert(fromValue value: T?) throws -> Self? { 55 | guard let value = value else { return nil } 56 | 57 | if let stringValue = value as? String { 58 | let rgba = try ColorConversionHelper.hexStringToRGBA(stringValue) 59 | return self.init(red: rgba.red, green: rgba.green, blue: rgba.blue, alpha: rgba.alpha) 60 | } 61 | 62 | throw ConversionError.unsupportedType 63 | } 64 | } 65 | 66 | #else 67 | 68 | import UIKit 69 | 70 | extension UIColor: Convertible { 71 | 72 | public static func convert(fromValue value: T?) throws -> Self? { 73 | guard let value = value else { return nil } 74 | 75 | if let stringValue = value as? String { 76 | let rgba = try ColorConversionHelper.hexStringToRGBA(stringValue) 77 | return self.init(red: rgba.red, green: rgba.green, blue: rgba.blue, alpha: rgba.alpha) 78 | } 79 | 80 | throw ConversionError.unsupportedType 81 | } 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/Date.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension Date: Convertible { 8 | fileprivate static let sharedFormatter = DateFormatter() 9 | 10 | public static func convert(fromValue value: T?) throws -> Date? { 11 | guard let value = value else { return nil } 12 | 13 | if let unixTimestamp = value as? Int { 14 | return self.init(timeIntervalSince1970: TimeInterval(unixTimestamp)) 15 | } else if let dateString = value as? String { 16 | if let convertedDate = JSONHelper.dateFormatter.date(from: dateString) { 17 | return self.init(timeIntervalSince1970: convertedDate.timeIntervalSince1970) 18 | } else { 19 | throw ConversionError.invalidValue 20 | } 21 | } 22 | 23 | throw ConversionError.unsupportedType 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/DecimalNumber.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension Decimal: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> Decimal? { 10 | guard let value = value else { return nil } 11 | 12 | if let doubleValue = value as? Double { 13 | return self.init(doubleValue) 14 | } else if let stringValue = value as? String { 15 | return self.init(string: stringValue) 16 | } else if let floatValue = value as? Float { 17 | return self.init(Double(floatValue)) 18 | } else if let intValue = value as? Int { 19 | return self.init(intValue) 20 | } 21 | 22 | throw ConversionError.unsupportedType 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/Double.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension Double: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> Double? { 10 | guard let value = value else { return nil } 11 | 12 | if let doubleValue = value as? Double { 13 | return doubleValue 14 | } else if let stringValue = value as? String { 15 | return Double(stringValue) 16 | } else if let floatValue = value as? Float { 17 | return Double(floatValue) 18 | } else if let intValue = value as? Int { 19 | return Double(intValue) 20 | } 21 | 22 | throw ConversionError.unsupportedType 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/Float.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension Float: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> Float? { 10 | guard let value = value else { return nil } 11 | 12 | if let floatValue = value as? Float { 13 | return floatValue 14 | } else if let stringValue = value as? String { 15 | return Float(stringValue) 16 | } else if let doubleValue = value as? Double { 17 | return Float(doubleValue) 18 | } else if let intValue = value as? Int { 19 | return Float(intValue) 20 | } 21 | 22 | throw ConversionError.unsupportedType 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/Int.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension Int: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> Int? { 10 | guard let value = value else { return nil } 11 | 12 | if let intValue = value as? Int { 13 | return intValue 14 | } else if let stringValue = value as? String { 15 | return Int(stringValue) 16 | } else if let floatValue = value as? Float { 17 | return Int(floatValue) 18 | } else if let doubleValue = value as? Double { 19 | return Int(doubleValue) 20 | } 21 | 22 | throw ConversionError.unsupportedType 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/String.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension String: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> String? { 10 | guard let value = value else { return nil } 11 | 12 | if let stringValue = value as? String { 13 | return stringValue 14 | } else if let intValue = value as? Int { 15 | return "\(intValue)" 16 | } else if let dateValue = value as? Date { 17 | return JSONHelper.dateFormatter.string(from: dateValue) 18 | } 19 | 20 | throw ConversionError.unsupportedType 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /JSONHelper/Extensions/URL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | extension URL: Convertible { 8 | 9 | public static func convert(fromValue value: T?) throws -> URL? { 10 | guard let value = value else { return nil } 11 | 12 | if let urlValue = value as? URL { 13 | return self.init(string: urlValue.absoluteString) 14 | } else if let stringValue = value as? String { 15 | return self.init(string: stringValue) 16 | } 17 | 18 | throw ConversionError.unsupportedType 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JSONHelper/JSONHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSONHelper.h 3 | // JSONHelper 4 | // 5 | // Created by Baris Sencan on 22/01/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for JSONHelper. 12 | FOUNDATION_EXPORT double JSONHelperVersionNumber; 13 | 14 | //! Project version string for JSONHelper. 15 | FOUNDATION_EXPORT const unsigned char JSONHelperVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /JSONHelper/JSONHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | open class JSONHelper { 8 | 9 | /// Date formatter that is used when converting strings to NSDate objects. 10 | open static var dateFormatter = DateFormatter() 11 | 12 | /// Filters out values of type NSNull. 13 | /// 14 | /// :param: value Value to check. 15 | /// 16 | /// :returns: nil if value is of type NSNull, else the value is returned as-is. 17 | open static func convertToNilIfNull(_ value: T?) -> T? { 18 | return (value is NSNull) ? nil : value 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JSONHelper/Serialization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | /// TODOC 8 | public protocol Serializable { 9 | 10 | /// TODOC 11 | func toDictionary() throws -> [String : Any] 12 | } 13 | 14 | // TODO 15 | -------------------------------------------------------------------------------- /JSONHelper/Support/JSONAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | //import Foundation 6 | // 7 | ///// Structure for holding a response returned by a JSON API server. 8 | //public struct JSONAPIResponse: Deserializable { 9 | // private(set) public var jsonapi = JSONAPISpecification() 10 | // private(set) public var links = JSONAPILinks() 11 | // private(set) public var data: AnyObject? = nil 12 | // private(set) public var included = [[String : AnyObject]]() 13 | // private(set) public var errors = [JSONAPIError]() 14 | // private(set) public var meta = [String : AnyObject]() 15 | // 16 | // /// The original raw response data, read-only. 17 | // public let raw: [String : AnyObject] 18 | // 19 | // public enum Fields: String { 20 | // case jsonapi, links, data, included, errors, meta 21 | // } 22 | // 23 | // public init(dictionary: [String : AnyObject]) throws { 24 | // try jsonapi <-- dictionary[Fields.jsonapi.rawValue] 25 | // try links <-- dictionary[Fields.links.rawValue] 26 | // self.data = dictionary[Fields.data.rawValue] 27 | // try included <-- dictionary[Fields.included.rawValue] 28 | // try errors <-- dictionary[Fields.errors.rawValue] 29 | // try meta <-- dictionary[Fields.meta.rawValue] 30 | // raw = dictionary 31 | // } 32 | // 33 | // public init() { 34 | // raw = [String : AnyObject]() 35 | // } 36 | // 37 | // /// Traverses the response `data` and replaces objects in `relationships` with 38 | // /// full objects from the `included` section of the response. 39 | // /// 40 | // /// This is an expensive operation and should only be used if needed. 41 | // public mutating func replaceRelationshipsInDataWithIncluded() { 42 | // if let dataDictionary = data as? [String : AnyObject] { 43 | // data = processDataDictionary(dataDictionary) 44 | // } else if let dataArray = data as? [[String : AnyObject]] { 45 | // var newData = [[String : AnyObject]]() 46 | // for dataDictionary in dataArray { 47 | // newData.append(processDataDictionary(dataDictionary)) 48 | // } 49 | // data = newData 50 | // } 51 | // } 52 | // 53 | // private func processDataDictionary(dataDictionary: [String : AnyObject]) -> [String : AnyObject] { 54 | // let resourceObject = (try? JSONAPIResourceObject(dictionary: dataDictionary)) ?? JSONAPIResourceObject() 55 | // var newData = [String : AnyObject]() 56 | // 57 | // for (key, value) in dataDictionary { 58 | // newData[key] = value 59 | // } 60 | // 61 | // var newRelationships = [String: [String : AnyObject]]() 62 | // for (relationshipName, relationshipObject) in resourceObject.relationships { 63 | // var newRelationship = [String : AnyObject]() 64 | // 65 | // if let links = dataDictionary["relationships"]?[relationshipName]??["links"] { 66 | // newRelationship["links"] = links 67 | // } 68 | // 69 | // if let relationshipDataDictionary = relationshipObject.data as? [String : AnyObject] { 70 | // newRelationship["data"] = processRelationshipDataDictionary(relationshipDataDictionary) 71 | // } else if let relationshipDataArray = relationshipObject.data as? [[String : AnyObject]] { 72 | // var newRelationshipData = [[String : AnyObject]]() 73 | // 74 | // for relationshipDataDictionary in relationshipDataArray { 75 | // newRelationshipData.append(processRelationshipDataDictionary(relationshipDataDictionary) ?? relationshipDataDictionary) 76 | // } 77 | // newRelationship["data"] = newRelationshipData 78 | // } 79 | // 80 | // if let meta = dataDictionary["relationships"]?[relationshipName]??["meta"] { 81 | // newRelationship["meta"] = meta 82 | // } 83 | // 84 | // newRelationships[relationshipName] = newRelationship 85 | // } 86 | // 87 | // newData["relationships"] = newRelationships 88 | // 89 | // return newData 90 | // } 91 | // 92 | // private func processRelationshipDataDictionary(relationshipDataDictionary: [String : AnyObject]) -> [String : AnyObject]? { 93 | // let idKey = JSONAPIResourceObject.BaseFields.id.rawValue 94 | // let typeKey = JSONAPIResourceObject.BaseFields.type.rawValue 95 | // 96 | // if let 97 | // relationshipObjectID = relationshipDataDictionary[idKey] as? String, 98 | // relationshipObjectType = relationshipDataDictionary[typeKey] as? String, 99 | // includedObject = getIncludedObjectOfType(relationshipObjectType, withID: relationshipObjectID) { 100 | // return includedObject 101 | // } 102 | // return nil 103 | // } 104 | // 105 | // public func getIncludedObjectOfType(type: String, withID id: String) -> [String : AnyObject]? { 106 | // let idKey = JSONAPIResourceObject.BaseFields.id.rawValue 107 | // let typeKey = JSONAPIResourceObject.BaseFields.type.rawValue 108 | // 109 | // for include in included { 110 | // if ((include[idKey] as? String) == id) && ((include[typeKey] as? String) == type) { 111 | // return include 112 | // } 113 | // } 114 | // return nil 115 | // } 116 | //} 117 | // 118 | //public struct JSONAPISpecification: Deserializable { 119 | // private(set) public var version = "1.0" 120 | // 121 | // public enum Field: String { 122 | // case version 123 | // } 124 | // 125 | // public init(dictionary: [String : AnyObject]) throws { 126 | // try version <-- dictionary[Field.version.rawValue] 127 | // } 128 | // 129 | // public init() {} 130 | //} 131 | // 132 | ///// A JSON API links object. http://jsonapi.org/format/#fetching-pagination 133 | //public struct JSONAPILinks: Deserializable { 134 | // private(set) public var current: JSONAPILink? = nil 135 | // private(set) public var about: JSONAPILink? = nil 136 | // private(set) public var related: JSONAPILink? = nil 137 | // private(set) public var first: JSONAPILink? = nil 138 | // private(set) public var last: JSONAPILink? = nil 139 | // private(set) public var prev: JSONAPILink? = nil 140 | // private(set) public var next: JSONAPILink? = nil 141 | // 142 | // public enum Field: String { 143 | // case current = "self" 144 | // case about = "about" 145 | // case related = "related" 146 | // case first = "first" 147 | // case last = "last" 148 | // case prev = "prev" 149 | // case next = "next" 150 | // } 151 | // 152 | // public init(dictionary: [String : AnyObject]) { 153 | // current = deserializeLink(dictionary[Field.current.rawValue]) 154 | // about = deserializeLink(dictionary[Field.about.rawValue]) 155 | // related = deserializeLink(dictionary[Field.related.rawValue]) 156 | // first = deserializeLink(dictionary[Field.first.rawValue]) 157 | // last = deserializeLink(dictionary[Field.last.rawValue]) 158 | // prev = deserializeLink(dictionary[Field.prev.rawValue]) 159 | // next = deserializeLink(dictionary[Field.next.rawValue]) 160 | // } 161 | // 162 | // private func deserializeLink(data: AnyObject?) -> JSONAPILink? { 163 | // do { 164 | // if let urlString = data as? String { 165 | // return try JSONAPILink(dictionary: [JSONAPILink.Field.href.rawValue: urlString]) 166 | // } 167 | // return try JSONAPILink(dictionary: (data as? [String : AnyObject]) ?? [:]) 168 | // } catch { 169 | // return nil 170 | // } 171 | // } 172 | // 173 | // public init() {} 174 | //} 175 | // 176 | ///// A JSON API link object. http://jsonapi.org/format/#document-links 177 | //public struct JSONAPILink: Deserializable { 178 | // private(set) public var href: NSURL? 179 | // private(set) public var meta = [String : AnyObject]() 180 | // 181 | // public enum Field: String { 182 | // case href, meta 183 | // } 184 | // 185 | // public init(dictionary: [String : AnyObject]) throws { 186 | // try href <-- dictionary[Field.href.rawValue] 187 | // try meta <-- dictionary[Field.meta.rawValue] 188 | // } 189 | //} 190 | // 191 | ///// A JSON API error object. http://jsonapi.org/format/#errors 192 | //public struct JSONAPIError: Deserializable { 193 | // private(set) public var id: String? 194 | // private(set) public var links = JSONAPILinks() 195 | // private(set) public var status: String? 196 | // private(set) public var code: String? 197 | // private(set) public var title: String? 198 | // private(set) public var detail: String? 199 | // private(set) public var source = JSONAPIErrorSource() 200 | // private(set) public var meta = [String : AnyObject]() 201 | // 202 | // public enum Field: String { 203 | // case id, links, status, code, title, detail, source, meta 204 | // } 205 | // 206 | // public init(dictionary: [String : AnyObject]) throws { 207 | // try id <-- dictionary[Field.id.rawValue] 208 | // try links <-- dictionary[Field.links.rawValue] 209 | // try status <-- dictionary[Field.status.rawValue] 210 | // try code <-- dictionary[Field.code.rawValue] 211 | // try title <-- dictionary[Field.title.rawValue] 212 | // try detail <-- dictionary[Field.detail.rawValue] 213 | // try source <-- dictionary[Field.source.rawValue] 214 | // try meta <-- dictionary[Field.meta.rawValue] 215 | // } 216 | //} 217 | // 218 | ///// A JSON API error source object. http://jsonapi.org/format/#errors 219 | //public struct JSONAPIErrorSource: Deserializable { 220 | // private(set) public var pointer: String? 221 | // private(set) public var parameter: String? 222 | // 223 | // public enum Field: String { 224 | // case pointer, parameter 225 | // } 226 | // 227 | // public init(dictionary: [String : AnyObject]) throws { 228 | // try pointer <-- dictionary[Field.pointer.rawValue] 229 | // try parameter <-- dictionary[Field.parameter.rawValue] 230 | // } 231 | // 232 | // public init() {} 233 | //} 234 | // 235 | ///// A JSON API resource object. http://jsonapi.org/format/#document-resource-objects 236 | //public struct JSONAPIResourceObject: Deserializable, Serializable { 237 | // private(set) public var id: String? 238 | // private(set) public var type: String? 239 | // private(set) public var attributes = [String : AnyObject]() 240 | // private(set) public var relationships = [String: JSONAPIRelationship]() 241 | // private(set) public var links = JSONAPILinks() 242 | // 243 | // // FIXME: Rename to Fields if possible. 244 | // public enum BaseFields: String { 245 | // case id, type, attributes, relationships, links 246 | // } 247 | // 248 | // public init(dictionary: [String : AnyObject]) throws { 249 | // try id <-- (dictionary[BaseFields.id.rawValue] ?? id) 250 | // try type <-- (dictionary[BaseFields.type.rawValue] ?? type) 251 | // try attributes <-- dictionary[BaseFields.attributes.rawValue] 252 | // try relationships <-- dictionary[BaseFields.relationships.rawValue] 253 | // try links <-- dictionary[BaseFields.links.rawValue] 254 | // } 255 | // 256 | // public init() {} 257 | // 258 | // public func toDictionary() -> [String : AnyObject] { 259 | // var dictionary = [String : AnyObject]() 260 | // 261 | // dictionary[BaseFields.id.rawValue] = id 262 | // dictionary[BaseFields.type.rawValue] = type 263 | // dictionary[BaseFields.attributes.rawValue] = attributes 264 | // 265 | // // TODO: relationships 266 | // 267 | // // TODO: links 268 | // 269 | // return dictionary 270 | // } 271 | // 272 | // public var description: String { 273 | // return toDictionary().description 274 | // } 275 | //} 276 | // 277 | ///// A JSON API relationship object. http://jsonapi.org/format/#document-resource-object-relationships 278 | //public struct JSONAPIRelationship: Deserializable { 279 | // private(set) public var links = JSONAPILinks() 280 | // private(set) public var data: AnyObject? 281 | // private(set) public var meta = [String : AnyObject]() 282 | // 283 | // public enum Field: String { 284 | // case links, data, meta 285 | // } 286 | // 287 | // public init(dictionary: [String : AnyObject]) throws { 288 | // try links <-- dictionary[Field.links.rawValue] 289 | // self.data = dictionary[Field.data.rawValue] 290 | // try meta <-- dictionary[Field.meta.rawValue] 291 | // } 292 | //} 293 | -------------------------------------------------------------------------------- /JSONHelper/Supporting Files/Mac/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /JSONHelper/Supporting Files/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /JSONHelper/Supporting Files/tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /JSONHelper/Supporting Files/tvOS/JSONHelper-tvOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSONHelper-tvOS.h 3 | // JSONHelper-tvOS 4 | // 5 | // Created by Baris Sencan on 30/11/2015. 6 | // Copyright © 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for JSONHelper-tvOS. 12 | FOUNDATION_EXPORT double JSONHelper_tvOSVersionNumber; 13 | 14 | //! Project version string for JSONHelper-tvOS. 15 | FOUNDATION_EXPORT const unsigned char JSONHelper_tvOSVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /JSONHelperExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // JSONHelperExample 4 | // 5 | // Created by Baris Sencan on 22/01/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /JSONHelperExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /JSONHelperExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /JSONHelperExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /JSONHelperExample/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /JSONHelperExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // JSONHelperExample 4 | // 5 | // Created by Baris Sencan on 22/01/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /JSONHelperExampleTests/JSONHelperExampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSONHelperExampleTests.swift 3 | // JSONHelperExampleTests 4 | // 5 | // Created by Baris Sencan on 22/01/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class JSONHelperExampleTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /JSONHelperExampleTests/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /JSONHelperTests/ArrayTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class ArrayTests: XCTestCase { 10 | 11 | // MARK: - Convertable Tests 12 | 13 | let urlStrings = ["http://apple.com", "http://google.com", "http://facebook.com"] 14 | let urlHosts = ["apple.com", "google.com", "facebook.com"] 15 | 16 | func testArrayToConvertibleArray() { 17 | var urls = [URL]() 18 | urls <-- urlStrings 19 | 20 | XCTAssertEqual(urls[0].host, urlHosts[0]) 21 | XCTAssertEqual(urls[1].host, urlHosts[1]) 22 | XCTAssertEqual(urls[2].host, urlHosts[2]) 23 | } 24 | 25 | func testArrayAsAnyToConvertibleArray() { 26 | var urls = [URL]() 27 | urls <-- (urlStrings as Any) 28 | 29 | XCTAssertEqual(urls[0].host, urlHosts[0]) 30 | XCTAssertEqual(urls[1].host, urlHosts[1]) 31 | XCTAssertEqual(urls[2].host, urlHosts[2]) 32 | } 33 | 34 | // MARK: - Deserializable Tests 35 | 36 | struct Item: Deserializable { 37 | static let nameKey = "name" 38 | 39 | var name: String? 40 | 41 | init(dictionary: [String: Any]) { 42 | name <-- dictionary[Item.nameKey] 43 | } 44 | } 45 | 46 | let dictionaries = [ 47 | [Item.nameKey : "a"], 48 | [Item.nameKey : "b"] 49 | ] 50 | 51 | func testArrayToDeserializableArray() { 52 | var items = [Item]() 53 | items <-- dictionaries 54 | XCTAssertEqual(items[0].name, "a") 55 | XCTAssertEqual(items[1].name, "b") 56 | } 57 | 58 | func testArrayAsAnyToDeserializableArray() { 59 | var items = [Item]() 60 | items <-- (dictionaries as Any) 61 | XCTAssertEqual(items[0].name, "a") 62 | XCTAssertEqual(items[1].name, "b") 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /JSONHelperTests/BoolTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class BoolTests: XCTestCase { 10 | let testBool = true 11 | let testIntsAndResults = [(-1, false), (0, false), (1, true), (2, true)] 12 | let testStringsAndResults = [("true", true), ("t", true), ("false", false), ("f", false), ("yes", true), ("y", true), ("no", false), ("n", false)] 13 | 14 | var value: Bool? 15 | 16 | override func setUp() { 17 | value = nil 18 | } 19 | 20 | func testBoolConversion() { 21 | value <-- (testBool as Any) 22 | XCTAssertEqual(value, testBool) 23 | } 24 | 25 | func testIntConversion() { 26 | for intAndResult in testIntsAndResults { 27 | value <-- (intAndResult.0 as Any) 28 | XCTAssertEqual(value, intAndResult.1) 29 | } 30 | } 31 | 32 | func testStringConversion() { 33 | for stringAndResult in testStringsAndResults { 34 | value <-- (stringAndResult.0 as Any) 35 | XCTAssertEqual(value, stringAndResult.1) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /JSONHelperTests/ColorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import XCTest 6 | import JSONHelper 7 | 8 | #if os(OSX) 9 | import AppKit 10 | #else 11 | import UIKit 12 | #endif 13 | 14 | class ColorTests: XCTestCase { 15 | let testStringAndResult = ("#ffffff", (r: CGFloat(1), g: CGFloat(1), b: CGFloat(1), a: CGFloat(1))) 16 | 17 | #if os(OSX) 18 | var value: NSColor? 19 | #else 20 | var value: UIColor? 21 | #endif 22 | 23 | override func setUp() { 24 | value = nil 25 | } 26 | 27 | func testStringConversion() { 28 | value <-- (testStringAndResult.0 as Any) 29 | 30 | var r: CGFloat = 0 31 | var g: CGFloat = 0 32 | var b: CGFloat = 0 33 | var a: CGFloat = 0 34 | value?.getRed(&r, green: &g, blue: &b, alpha: &a) 35 | 36 | XCTAssert( 37 | (r == testStringAndResult.1.r) && (g == testStringAndResult.1.g) && (b == testStringAndResult.1.b) && (a == testStringAndResult.1.a), 38 | "String to (UI/NS)Color conversion failed") 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /JSONHelperTests/DateTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class DateTests: XCTestCase { 10 | let dateString = "2016-04-14" 11 | let dateStringFormat = "yyyy-MM-dd" 12 | let epochTimestamp = 1460592000 13 | 14 | override func setUp() { 15 | JSONHelper.dateFormatter.dateFormat = dateStringFormat 16 | JSONHelper.dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) 17 | } 18 | 19 | func testEpochTimestampConversion() { 20 | var date = Date() 21 | date <-- (epochTimestamp as Any) 22 | XCTAssertEqual(JSONHelper.dateFormatter.string(from: date), dateString) 23 | } 24 | 25 | func testStringConversion() { 26 | var date = Date() 27 | date <-- (dateString as Any) 28 | XCTAssertEqual(JSONHelper.dateFormatter.string(from: date), dateString) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /JSONHelperTests/DecimalTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class DecimalTests: XCTestCase { 10 | let testInt = 1 11 | let testFloat = Float(1.5) 12 | let testDouble = Double(1.5) 13 | let testDecimal = Decimal(1.5) 14 | let testNSNumber = NSNumber(value: 1.5 as Double) 15 | let testNSDecimalNumber = NSDecimalNumber(value: 1.5 as Double) 16 | let testString = "1.5" 17 | 18 | var value = Decimal(0) 19 | 20 | override func setUp() { 21 | value = Decimal(0) 22 | } 23 | 24 | func testIntConversion() { 25 | value <-- (testInt as Any) 26 | XCTAssertEqual(Int(NSDecimalNumber(decimal: value)), testInt) 27 | } 28 | 29 | func testFloatConversion() { 30 | value <-- (testFloat as Any) 31 | XCTAssertEqual(value, testDecimal) 32 | } 33 | 34 | func testDoubleConversion() { 35 | value <-- (testDouble as Any) 36 | XCTAssertEqual(value, testDecimal) 37 | } 38 | 39 | func testNSNumberConversion() { 40 | value <-- (testNSNumber as Any) 41 | XCTAssertEqual(value, testDecimal) 42 | } 43 | 44 | func testNSDecimalNumberConversion() { 45 | value <-- (testNSDecimalNumber as Any) 46 | XCTAssertEqual(value, testDecimal) 47 | } 48 | 49 | func testStringConversion() { 50 | value <-- (testString as Any) 51 | XCTAssertEqual(value, testDecimal) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /JSONHelperTests/DeserializableTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class DeserializableTests: XCTestCase { 10 | 11 | struct Item: Deserializable { 12 | static let nameKey = "name" 13 | 14 | var name = "" 15 | 16 | init(dictionary: [String : Any]) { 17 | name <-- dictionary[Item.nameKey] 18 | } 19 | 20 | init() {} 21 | } 22 | 23 | let itemDictionary = [Item.nameKey : "a"] 24 | let itemString = "{ \"name\": \"a\" }" 25 | 26 | var item = Item() 27 | 28 | override func setUp() { 29 | item = Item() 30 | } 31 | 32 | func testDictionaryDeserialization() { 33 | item <-- itemDictionary 34 | XCTAssertEqual(item.name, itemDictionary[Item.nameKey]) 35 | } 36 | 37 | func testStringDeserialization() { 38 | item <-- itemString 39 | XCTAssertEqual(item.name, itemDictionary[Item.nameKey]) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /JSONHelperTests/DictionaryTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class DictionaryTests: XCTestCase { 10 | 11 | // MARK: - Convertible Tests 12 | 13 | let dateStringDictionary = ["one" : "2014-11-02", "two" : "2015-04-24"] 14 | 15 | override func setUp() { 16 | JSONHelper.dateFormatter.dateFormat = "yyyy-MM-dd" 17 | } 18 | 19 | func testDictionaryToConvertibleDictionary() { 20 | var value = [String : Date]() 21 | value <-- dateStringDictionary 22 | XCTAssertEqual(JSONHelper.dateFormatter.string(from: value["one"]!), dateStringDictionary["one"]) 23 | } 24 | 25 | func testDictionaryAsAnyToConvertibleDictionary() { 26 | var value = [String : Date]() 27 | value <-- (dateStringDictionary as Any) 28 | XCTAssertEqual(JSONHelper.dateFormatter.string(from: value["one"]!), dateStringDictionary["one"]) 29 | } 30 | 31 | // MARK: - Deserializable Tests 32 | 33 | let dictionary = [ 34 | "one" : ["name" : "a"], 35 | "two" : ["name" : "b"] 36 | ] 37 | 38 | struct Item: Deserializable { 39 | static let nameKey = "name" 40 | 41 | var name = "" 42 | 43 | init(dictionary: [String : Any]) { 44 | name <-- dictionary["name"] 45 | } 46 | } 47 | 48 | func testDictionaryToMappableDictionary() { 49 | var value = [String : Item]() 50 | value <-- dictionary 51 | XCTAssertEqual(value["one"]?.name, dictionary["one"]?["name"]) 52 | XCTAssertEqual(value["two"]?.name, dictionary["two"]?["name"]) 53 | } 54 | 55 | func testDictionaryAsAnyToMappableDictionary() { 56 | var value = [String : Item]() 57 | value <-- (dictionary as Any) 58 | XCTAssertEqual(value["one"]?.name, dictionary["one"]?["name"]) 59 | XCTAssertEqual(value["two"]?.name, dictionary["two"]?["name"]) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JSONHelperTests/DoubleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class DoubleTests: XCTestCase { 10 | let testInt = 1 11 | let testFloat = Float(1.5) 12 | let testDouble = Double(1.5) 13 | let testNSNumber = NSNumber(value: 1.5 as Double) 14 | let testNSDecimalNumber = NSDecimalNumber(value: 1.5 as Double) 15 | let testString = "1.5" 16 | 17 | var value = 0.0 18 | 19 | override func setUp() { 20 | value = 0.0 21 | } 22 | 23 | func testIntConversion() { 24 | value <-- (testInt as Any) 25 | XCTAssert(Int(value) == testInt) 26 | } 27 | 28 | func testFloatConversion() { 29 | value <-- (testFloat as Any) 30 | XCTAssertEqual(value, testDouble) 31 | } 32 | 33 | func testDoubleConversion() { 34 | value <-- (testDouble as Any) 35 | XCTAssertEqual(value, testDouble) 36 | } 37 | 38 | func testNSNumberConversion() { 39 | value <-- (testNSNumber as Any) 40 | XCTAssertEqual(value, testDouble) 41 | } 42 | 43 | func testNSDecimalNumberConversion() { 44 | value <-- (testNSDecimalNumber as Any) 45 | XCTAssertEqual(value, testDouble) 46 | } 47 | 48 | func testStringConversion() { 49 | value <-- (testString as Any) 50 | XCTAssertEqual(value, testDouble) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /JSONHelperTests/EnumTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class EnumTests: XCTestCase { 10 | 11 | enum TestEnum: String { 12 | case Hello, Darkness, My, Old, Friend 13 | } 14 | 15 | var value = TestEnum.Hello 16 | 17 | override func setUp() { 18 | value = .Hello 19 | } 20 | 21 | func testStringConversion() { 22 | value <-- (TestEnum.Friend.rawValue as Any) 23 | XCTAssertEqual(value, TestEnum.Friend) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /JSONHelperTests/FloatTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class FloatTests: XCTestCase { 10 | let testInt = 1 11 | let testFloat = Float(1.5) 12 | let testDouble = Double(1.5) 13 | let testNSNumber = NSNumber(value: 1.5 as Double) 14 | let testNSDecimalNumber = NSDecimalNumber(value: 1.5 as Double) 15 | let testString = "1.5" 16 | 17 | var value = Float(0) 18 | 19 | override func setUp() { 20 | value = Float(0) 21 | } 22 | 23 | func testIntConversion() { 24 | value <-- (testInt as Any) 25 | XCTAssertEqual(Int(value), testInt) 26 | } 27 | 28 | func testFloatConversion() { 29 | value <-- (testFloat as Any) 30 | XCTAssertEqual(value, testFloat) 31 | } 32 | 33 | func testDoubleConversion() { 34 | value <-- (testDouble as Any) 35 | XCTAssertEqual(value, testFloat) 36 | } 37 | 38 | func testNSNumberConversion() { 39 | value <-- (testNSNumber as Any) 40 | XCTAssertEqual(value, testFloat) 41 | } 42 | 43 | func testNSDecimalNumberConversion() { 44 | value <-- (testNSDecimalNumber as Any) 45 | XCTAssertEqual(value, testFloat) 46 | } 47 | 48 | func testStringConversion() { 49 | value <-- (testString as Any) 50 | XCTAssertEqual(value, testFloat) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /JSONHelperTests/IntTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntTests.swift 3 | // JSONHelper 4 | // 5 | // Created by Baris Sencan on 6/29/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import JSONHelper 12 | 13 | class IntTests: XCTestCase { 14 | let testInt = 1 15 | let testFloat = Float(1) 16 | let testDouble = Double(1) 17 | let testNSNumber = NSNumber(value: 1 as Int) 18 | let testNSDecimalNumber = NSDecimalNumber(value: 1 as Int) 19 | let testString = "1" 20 | 21 | var value = 0 22 | 23 | override func setUp() { 24 | value = 0 25 | } 26 | 27 | func testIntConversion() { 28 | value <-- (testInt as Any) 29 | XCTAssertEqual(value, testInt) 30 | } 31 | 32 | func testFloatConversion() { 33 | value <-- (testFloat as Any) 34 | XCTAssertEqual(value, testInt) 35 | } 36 | 37 | func testDoubleConversion() { 38 | value <-- (testDouble as Any) 39 | XCTAssertEqual(value, testInt) 40 | } 41 | 42 | func testNSNumberConversion() { 43 | value <-- (testNSNumber as Any) 44 | XCTAssertEqual(value, testInt) 45 | } 46 | 47 | func testNSDecimalNumberConversion() { 48 | value <-- (testNSDecimalNumber as Any) 49 | XCTAssertEqual(value, testInt) 50 | } 51 | 52 | func testStringConversion() { 53 | value <-- (testString as Any) 54 | XCTAssertEqual(value, testInt) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /JSONHelperTests/JSONHelperTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016 Baris Sencan. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | import XCTest 7 | import JSONHelper 8 | 9 | class JSONHelperTests: XCTestCase { 10 | 11 | func testConvertToNilIfNull() { 12 | let nilValues: [AnyObject?] = [NSNull(), nil] 13 | let nonNilValues = [0, "", false, [], [:]] as [Any] 14 | 15 | for nilValue in nilValues { 16 | XCTAssert(JSONHelper.convertToNilIfNull(nilValue) == nil) 17 | } 18 | 19 | for nonNilValue in nonNilValues { 20 | XCTAssert(JSONHelper.convertToNilIfNull(nonNilValue) != nil) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /JSONHelperTests/StringTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StringTests.swift 3 | // JSONHelper 4 | // 5 | // Created by Baris Sencan on 6/22/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import JSONHelper 12 | 13 | class StringTests: XCTestCase { 14 | let testString = "test" 15 | let testIntAndResult = (1, "1") 16 | let testDateAndResult = (Date(timeIntervalSince1970: 0), "1970-01-01") 17 | let testDateFormat = "yyyy-MM-dd" 18 | 19 | var value = "" 20 | 21 | override func setUp() { 22 | value = "" 23 | } 24 | 25 | func testStringConversion() { 26 | value <-- (testString as Any) 27 | XCTAssertEqual(value, testString) 28 | } 29 | 30 | func testIntConversion() { 31 | value <-- (testIntAndResult.0 as Any) 32 | XCTAssertEqual(value, testIntAndResult.1) 33 | } 34 | 35 | func testDateConversion() { 36 | JSONHelper.dateFormatter.dateFormat = testDateFormat 37 | JSONHelper.dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) 38 | 39 | value <-- (testDateAndResult.0 as Any) 40 | XCTAssertEqual(value, testDateAndResult.1) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /JSONHelperTests/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /JSONHelperTests/URLTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLTests.swift 3 | // JSONHelper 4 | // 5 | // Created by Baris Sencan on 22/01/2016. 6 | // Copyright © 2016 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import JSONHelper 12 | 13 | class URLTests: XCTestCase { 14 | let urlString = "https://facebook.com" 15 | let urlHost = "facebook.com" 16 | 17 | func testStringConversion() { 18 | var url: URL? 19 | url <-- (urlString as Any) 20 | XCTAssertEqual(url?.host, urlHost) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | JSONHelper 2 | 3 | Copyright (C) 2014 Baris Sencan 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source distribution. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JSONHelper [![CocoaPods](https://img.shields.io/cocoapods/l/JSONHelper.svg)](https://github.com/isair/JSONHelper/blob/master/LICENSE) ![CocoaPods](https://img.shields.io/cocoapods/p/JSONHelper.svg) 2 | ----- 3 | 4 | [![Build Status](https://travis-ci.org/isair/JSONHelper.svg?branch=master)](https://travis-ci.org/isair/JSONHelper) 5 | [![CocoaPods](https://img.shields.io/cocoapods/v/JSONHelper.svg)](https://cocoapods.org/pods/JSONHelper) 6 | [![Gitter](https://badges.gitter.im/JOINCHAT.svg)](https://gitter.im/isair/JSONHelper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 | 8 | Convert anything into anything in one operation; hex strings into UIColor/NSColor, JSON strings into class instances, y/n strings to booleans, arrays and dictionaries of these; anything you can make sense of! 9 | 10 | __Latest version requires iOS 8+ and Xcode 7.3+__ 11 | 12 | 13 | Sponsor 14 | 15 | 16 | ## Table of Contents 17 | 18 | 1. [Installation](#installation) 19 | 2. [The <-- Operator](#the----operator) 20 | 3. [Convertible Protocol](#convertible-protocol) 21 | 4. [Deserializable Protocol](#deserializable-protocol) (with JSON deserialization example) 22 | 5. [Serializable Protocol](#serializable-protocol) 23 | 24 | ## Installation 25 | 26 | ### [CocoaPods](https://github.com/CocoaPods/CocoaPods) 27 | 28 | Add the following line in your `Podfile`. 29 | 30 | ``` 31 | pod "JSONHelper" 32 | ``` 33 | 34 | ### [Carthage](https://github.com/Carthage/Carthage#installing-carthage) 35 | 36 | Add the following line to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). 37 | 38 | ``` 39 | github "isair/JSONHelper" 40 | ``` 41 | 42 | Then do `carthage update`. After that, add the framework to your project. 43 | 44 | ## The <-- Operator 45 | 46 | The `<--` operator takes the value on its right hand side and tries to convert it into the type of the value on its left hand side. If the conversion fails, an error is logged on debug builds. If it's successful, the value of the left hand side variable is overwritten. It's chainable as well. 47 | 48 | If the right hand side value is nil or the conversion fails, and the left hand side variable is an optional, then nil is assigned to it. When the left hand side is non-optional, the current value of the left hand side variable is left untouched. 49 | 50 | Using this specification let's assume you have a dictionary response that you retrieved from some API with hex color strings in it, under the key `colors`, that you want to convert into an array of UIColor instances. Also, to fully use everything we know, let's also assume that we want to have a default value for our color array in case the value for the key we're looking for does not exist (is nil). 51 | 52 | ```swift 53 | var colors = [UIColor.blackColor(), UIColor.whiteColor()] 54 | // Assume we have response { "colors": ["#aaa", "#b06200aa"] } 55 | colors <-- response[colorsKey] 56 | ``` 57 | 58 | ### Convertible Protocol 59 | 60 | If your type is a simple value-like type, adopting the Convertible protocol is the way to make your type work with the `<--` operator. 61 | 62 | Example: 63 | ```swift 64 | struct Vector2D: Convertible { 65 | var x: Double = 0 66 | var y: Double = 0 67 | 68 | init(x: Double, y: Double) { 69 | self.x = x 70 | self.y = y 71 | } 72 | 73 | static func convertFromValue(value: T?) throws -> Self? { 74 | guard let value = value else { return nil } 75 | 76 | if let doubleTupleValue = value as? (Double, Double) { 77 | return self.init(x: doubleTupleValue.0, y: doubleTupleValue.1) 78 | } 79 | 80 | throw ConversionError.UnsupportedType 81 | } 82 | } 83 | ``` 84 | 85 | ```swift 86 | var myVector: Vector2D? 87 | myVector <-- (1.0, 2.7) 88 | ``` 89 | 90 | ### Deserializable Protocol 91 | 92 | While you can basically adopt the `Convertible` protocol for any type, if your type is always converted from a dictionary or a JSON string then things can get a lot easier with the `Deserializable` protocol. 93 | 94 | Example: 95 | ```swift 96 | class User: Deserializable { 97 | static let idKey = "id" 98 | static let emailKey = "email" 99 | static let nameKey = "name" 100 | static let avatarURLKey = "avatar_url" 101 | 102 | private(set) var id: String? 103 | private(set) var email: String? 104 | private(set) var name = "Guest" 105 | private(set) var avatarURL = NSURL(string: "https://mysite.com/assets/default-avatar.png") 106 | 107 | required init(dictionary: [String : AnyObject]) { 108 | id <-- dictionary[User.idKey] 109 | email <-- dictionary[User.emailKey] 110 | name <-- dictionary[User.nameKey] 111 | avatarURL <-- dictionary[User.avatarURLKey] 112 | } 113 | } 114 | ``` 115 | 116 | ```swift 117 | var myUser: User? 118 | user <-- apiResponse["user"] 119 | ``` 120 | 121 | ### Serializable Protocol 122 | 123 | // Serialization is coming soon. I'll probably not add a new protocol and just rename and update the Deserializable protocol and turn it into a mixin. 124 | -------------------------------------------------------------------------------- /scripts/install-fast.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Check project requirements 4 | 5 | check_required_bin() { 6 | if ! hash $1 2>/dev/null; then 7 | echo "$1 not found." 8 | exit 1 9 | fi 10 | } 11 | 12 | check_requirements() { 13 | check_required_bin rbenv 14 | check_required_bin bundle 15 | check_required_bin xcodebuild 16 | } 17 | 18 | printf "Checking project requirements... " 19 | check_requirements 20 | echo "done." 21 | 22 | # Initialize project 23 | 24 | cd "$(dirname "$0")/.." 25 | 26 | bundle install --path vendor/bundle 27 | -------------------------------------------------------------------------------- /scripts/install-travis.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Initialize project 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | bundle install --path vendor/bundle 8 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Check project requirements 4 | 5 | check_required_bin() { 6 | if ! hash $1 2>/dev/null; then 7 | echo "$1 not found." 8 | exit 1 9 | fi 10 | } 11 | 12 | check_requirements() { 13 | check_required_bin rbenv 14 | check_required_bin ruby-build 15 | check_required_bin xcodebuild 16 | } 17 | 18 | printf "Checking project requirements... " 19 | check_requirements 20 | echo "done." 21 | 22 | # Initialize project 23 | 24 | cd "$(dirname "$0")/.." 25 | 26 | RUBY_VERSION=`cat .ruby-version` 27 | rbenv install -s $RUBY_VERSION 28 | 29 | gem install bundler 30 | rbenv rehash 31 | 32 | bundle install --path vendor/bundle 33 | -------------------------------------------------------------------------------- /scripts/pod-lint.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | cd "$(dirname "$0")/.." 4 | 5 | bundle exec pod spec lint JSONHelper.podspec --allow-warnings 6 | -------------------------------------------------------------------------------- /scripts/pod-push.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | cd "$(dirname "$0")/.." 4 | 5 | bundle exec pod trunk push JSONHelper.podspec --allow-warnings 6 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | cd "$(dirname "$0")/.." 4 | 5 | xcodebuild test -project JSONHelper.xcodeproj -scheme JSONHelper -destination 'platform=iOS Simulator,name=iPhone SE' -derivedDataPath='./build' | bundle exec xcpretty 6 | 7 | IOS_STATUS=${PIPESTATUS[0]} 8 | 9 | xcodebuild test -project JSONHelper.xcodeproj -scheme JSONHelper -destination 'platform=OS X,arch=x86_64' | bundle exec xcpretty 10 | 11 | MAC_STATUS=${PIPESTATUS[0]} 12 | 13 | xcodebuild test -project JSONHelper.xcodeproj -scheme JSONHelper -destination 'platform=tvOS Simulator,name=Apple TV 1080p' | bundle exec xcpretty 14 | 15 | TVOS_STATUS=${PIPESTATUS[0]} 16 | 17 | if [[ $IOS_STATUS == 0 && $MAC_STATUS == 0 && $TVOS_STATUS == 0 ]]; then 18 | echo "All tests have passed." 19 | exit 0 20 | else 21 | echo "Some tests have failed." 22 | exit 1 23 | fi 24 | --------------------------------------------------------------------------------