├── .gitignore ├── Cartfile ├── Cartfile.resolved ├── JSONShootout.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── JSONShootout.xcscheme ├── JSONShootout.xcworkspace └── contents.xcworkspacedata ├── JSONShootout ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist └── ViewController.swift ├── JSONShootoutTests ├── Decodable_Tests.swift ├── Freddy_Tests.swift ├── Genome_Test.swift ├── Gloss_Tests.swift ├── Info.plist ├── JSON_Tests.swift ├── Large.json ├── Mapper_Tests.swift ├── Marshal_Tests.swift ├── ObjectMapper_Test.swift ├── PMJSON_Tests.swift ├── SwiftyJSON_Tests.swift └── Unbox_Tests.swift ├── ModelObjects ├── Info.plist ├── ModelObjects.h ├── NSDate+JSON.swift ├── Program+Decodable.swift ├── Program+Freddy.swift ├── Program+Genome.swift ├── Program+Gloss.swift ├── Program+JSON.swift ├── Program+Mapper.swift ├── Program+Marshal.swift ├── Program+ObjectMapper.swift ├── Program+PMJSON.swift ├── Program+SwiftyJSON.swift ├── Program+Unbox.swift ├── Program.swift ├── Recording+Decodable.swift ├── Recording+Freddy.swift ├── Recording+Genome.swift ├── Recording+Gloss.swift ├── Recording+JSON.swift ├── Recording+Mapper.swift ├── Recording+Marshal.swift ├── Recording+ObjectMapper.swift ├── Recording+PMJSON.swift ├── Recording+SwiftyJSON.swift ├── Recording+Unbox.swift └── Recording.swift ├── README.md └── images └── performance.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/xcode,swift 3 | 4 | ### Xcode ### 5 | # Xcode 6 | # 7 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 8 | 9 | ## Build generated 10 | build/ 11 | DerivedData/ 12 | 13 | ## Various settings 14 | *.pbxuser 15 | !default.pbxuser 16 | *.mode1v3 17 | !default.mode1v3 18 | *.mode2v3 19 | !default.mode2v3 20 | *.perspectivev3 21 | !default.perspectivev3 22 | xcuserdata/ 23 | 24 | ## Other 25 | *.moved-aside 26 | *.xccheckout 27 | *.xcscmblueprint 28 | 29 | 30 | ### Swift ### 31 | # Xcode 32 | # 33 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 34 | 35 | ## Build generated 36 | build/ 37 | DerivedData/ 38 | 39 | ## Various settings 40 | *.pbxuser 41 | !default.pbxuser 42 | *.mode1v3 43 | !default.mode1v3 44 | *.mode2v3 45 | !default.mode2v3 46 | *.perspectivev3 47 | !default.perspectivev3 48 | xcuserdata/ 49 | 50 | ## Other 51 | *.moved-aside 52 | *.xcuserstate 53 | 54 | ## Obj-C/Swift specific 55 | *.hmap 56 | *.ipa 57 | *.dSYM.zip 58 | *.dSYM 59 | 60 | ## Playgrounds 61 | timeline.xctimeline 62 | playground.xcworkspace 63 | 64 | # Swift Package Manager 65 | # 66 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 67 | # Packages/ 68 | .build/ 69 | 70 | # CocoaPods 71 | # 72 | # We recommend against adding the Pods directory to your .gitignore. However 73 | # you should judge for yourself, the pros and cons are mentioned at: 74 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 75 | # 76 | # Pods/ 77 | 78 | # Carthage 79 | # 80 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 81 | Carthage/Checkouts 82 | 83 | Carthage/Build 84 | 85 | # fastlane 86 | # 87 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 88 | # screenshots whenever they are needed. 89 | # For more information about the recommended setup visit: 90 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 91 | 92 | fastlane/report.xml 93 | fastlane/Preview.html 94 | fastlane/screenshots 95 | fastlane/test_output 96 | 97 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "utahiosmac/Marshal" "master" 2 | github "lyft/mapper" "master" 3 | github "JohnSundell/Unbox" "master" 4 | github "SwiftyJSON/SwiftyJSON" "master" 5 | github "Anviking/Decodable" "master" 6 | github "Hearst-DD/ObjectMapper" ~> 2.2 7 | github "vdka/json" ~> 0.15 8 | github "hkellaway/Gloss" "master" 9 | github "LoganWright/Genome" == 3.0.3 10 | github "postmates/PMJSON" "master" 11 | github "bignerdranch/Freddy" ~> 3.0 12 | 13 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "Anviking/Decodable" "ba6b6fb83e0df6f709acd5f2cdd9da8b49492708" 2 | github "bignerdranch/Freddy" "3.0.2" 3 | github "LoganWright/Genome" "3.0.3" 4 | github "hkellaway/Gloss" "27242cb5175958ce43395ff837f63967ba111d4a" 5 | github "utahiosmac/Marshal" "7a814e26312d5e7f1209168ca1a7860dcc12cf5f" 6 | github "Hearst-DD/ObjectMapper" "2.2.2" 7 | github "postmates/PMJSON" "c21e8b9dbf47db2f1a16d7aba453b7844c0cff10" 8 | github "SwiftyJSON/SwiftyJSON" "adf34cfb4c9f2ff4e3c420c6d9fb1e2eaf3b3791" 9 | github "JohnSundell/Unbox" "0466fcb72ee1454a302d3ee6640f19fec4c0e037" 10 | github "vdka/json" "0.15.0" 11 | github "lyft/mapper" "4031d7d7c8b111af564a4f5d5970cf5d68747a03" 12 | -------------------------------------------------------------------------------- /JSONShootout.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2098D54A1DC1F5E800A15075 /* Genome.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2098D5491DC1F5E800A15075 /* Genome.framework */; }; 11 | 2098D54B1DC1F5E800A15075 /* Genome.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2098D5491DC1F5E800A15075 /* Genome.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 12 | 2098D54C1DC1F5FB00A15075 /* Genome.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2098D5491DC1F5E800A15075 /* Genome.framework */; }; 13 | 20A0B9571DC2584D001D8A14 /* Recording+Genome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20A0B9561DC2584D001D8A14 /* Recording+Genome.swift */; }; 14 | 20A0B9591DC25B60001D8A14 /* Program+Genome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20A0B9581DC25B60001D8A14 /* Program+Genome.swift */; }; 15 | 20A0B95B1DC25F03001D8A14 /* Genome_Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20A0B95A1DC25F03001D8A14 /* Genome_Test.swift */; }; 16 | 20A0B96B1DC26810001D8A14 /* GenomeFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20A0B9691DC26803001D8A14 /* GenomeFoundation.framework */; }; 17 | 2F2868961DE7F34B002A6F68 /* Freddy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F2868951DE7F34B002A6F68 /* Freddy.framework */; }; 18 | 2F2868981DE7F48A002A6F68 /* Freddy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F2868971DE7F48A002A6F68 /* Freddy.framework */; }; 19 | 2F28689A1DE7F502002A6F68 /* Freddy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2F2868971DE7F48A002A6F68 /* Freddy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 20 | 2F28689C1DE7F66F002A6F68 /* Freddy_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F28689B1DE7F66F002A6F68 /* Freddy_Tests.swift */; }; 21 | 2F28689E1DE7FB58002A6F68 /* Program+Freddy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F28689D1DE7FB58002A6F68 /* Program+Freddy.swift */; }; 22 | 2F2868A01DE8843C002A6F68 /* Recording+Freddy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F28689F1DE8843C002A6F68 /* Recording+Freddy.swift */; }; 23 | 5B69A1DA1DBEC84200B12579 /* Recording+Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B69A1D91DBEC84200B12579 /* Recording+Decodable.swift */; }; 24 | 5B69A1DC1DBEC86A00B12579 /* Program+Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B69A1DB1DBEC86A00B12579 /* Program+Decodable.swift */; }; 25 | 5B69A1DE1DBEC9A400B12579 /* Decodable_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B69A1DD1DBEC9A400B12579 /* Decodable_Tests.swift */; }; 26 | 5BA72ECF1DBECC0C007ADBAE /* ModelObjects.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC97869E1CEBABE7005A5DEA /* ModelObjects.framework */; }; 27 | 5BA72ED31DBECD52007ADBAE /* Decodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BA72EC71DBECA48007ADBAE /* Decodable.framework */; }; 28 | 681299051DBFFCAB009960BE /* ObjectMapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 681299041DBFFCAB009960BE /* ObjectMapper.framework */; }; 29 | 681299061DBFFCAB009960BE /* ObjectMapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 681299041DBFFCAB009960BE /* ObjectMapper.framework */; }; 30 | 681299071DBFFCBC009960BE /* ObjectMapper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 681299041DBFFCAB009960BE /* ObjectMapper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 31 | 681299181DC00DB1009960BE /* ObjectMapper_Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681299171DC00DB1009960BE /* ObjectMapper_Test.swift */; }; 32 | 6812991B1DC00DBB009960BE /* Program+ObjectMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 681299191DC00DBB009960BE /* Program+ObjectMapper.swift */; }; 33 | 6812991C1DC00DBB009960BE /* Recording+ObjectMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6812991A1DC00DBB009960BE /* Recording+ObjectMapper.swift */; }; 34 | 71337C8B1DBEBC6B00DCA374 /* Recording+Marshal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C8A1DBEBC6B00DCA374 /* Recording+Marshal.swift */; }; 35 | 71337C8D1DBEBC7900DCA374 /* Recording+Mapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C8C1DBEBC7900DCA374 /* Recording+Mapper.swift */; }; 36 | 71337C8F1DBEBC8600DCA374 /* Recording+Unbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C8E1DBEBC8600DCA374 /* Recording+Unbox.swift */; }; 37 | 71337C911DBEBCA300DCA374 /* Recording+SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C901DBEBCA300DCA374 /* Recording+SwiftyJSON.swift */; }; 38 | 71337C931DBEBFB400DCA374 /* Program+Marshal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C921DBEBFB400DCA374 /* Program+Marshal.swift */; }; 39 | 71337C951DBEBFC300DCA374 /* Program+Mapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C941DBEBFC300DCA374 /* Program+Mapper.swift */; }; 40 | 71337C971DBEBFD000DCA374 /* Program+Unbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C961DBEBFD000DCA374 /* Program+Unbox.swift */; }; 41 | 71337C991DBEBFDC00DCA374 /* Program+SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71337C981DBEBFDC00DCA374 /* Program+SwiftyJSON.swift */; }; 42 | 716A8A981DC1D0E900BF314B /* Gloss.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 716A8A971DC1D0E900BF314B /* Gloss.framework */; }; 43 | 716A8A9A1DC1D10A00BF314B /* Gloss.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C3FCD2D1DC1B19E00C82DEE /* Gloss.framework */; }; 44 | 716A8A9B1DC1D10A00BF314B /* Gloss.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7C3FCD2D1DC1B19E00C82DEE /* Gloss.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 45 | 716A8A9D1DC1D18B00BF314B /* JSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 716A8A9C1DC1D18B00BF314B /* JSON.framework */; }; 46 | 7C3FCD311DC1B2A100C82DEE /* Program+Gloss.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3FCD301DC1B2A100C82DEE /* Program+Gloss.swift */; }; 47 | 7C3FCD331DC1B2AE00C82DEE /* Recording+Gloss.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3FCD321DC1B2AE00C82DEE /* Recording+Gloss.swift */; }; 48 | 7C3FCD351DC1B61600C82DEE /* Gloss_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3FCD341DC1B61600C82DEE /* Gloss_Tests.swift */; }; 49 | 9E9BF9C81DCD116900548161 /* PMJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E9BF9C71DCD116900548161 /* PMJSON.framework */; }; 50 | 9E9BF9CA1DCD117300548161 /* PMJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E9BF9C91DCD117300548161 /* PMJSON.framework */; }; 51 | 9E9BF9CC1DCD11BA00548161 /* PMJSON_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BF9CB1DCD11BA00548161 /* PMJSON_Tests.swift */; }; 52 | 9E9BF9CE1DCD126D00548161 /* Program+PMJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BF9CD1DCD126D00548161 /* Program+PMJSON.swift */; }; 53 | 9E9BF9D01DCD307200548161 /* Recording+PMJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BF9CF1DCD307200548161 /* Recording+PMJSON.swift */; }; 54 | AA2B38CB1DC0B4AE008CECCD /* JSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA2B38CA1DC0B4AE008CECCD /* JSON.framework */; }; 55 | AA2B38CC1DC0B4AE008CECCD /* JSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AA2B38CA1DC0B4AE008CECCD /* JSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 56 | AA2B38D01DC0B4D2008CECCD /* Program+JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2B38CD1DC0B4CC008CECCD /* Program+JSON.swift */; }; 57 | AA2B38D21DC0B57F008CECCD /* Recording+JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2B38D11DC0B57F008CECCD /* Recording+JSON.swift */; }; 58 | AA2B38D41DC0B6D3008CECCD /* JSON_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2B38D31DC0B6D3008CECCD /* JSON_Tests.swift */; }; 59 | CC3023411CF9616600B51746 /* Unbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C51CEBACE8005A5DEA /* Unbox.framework */; }; 60 | CC3023421CF9616600B51746 /* Unbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C51CEBACE8005A5DEA /* Unbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 61 | CC3023431CF9616600B51746 /* Marshal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C31CEBACD5005A5DEA /* Marshal.framework */; }; 62 | CC3023441CF9616600B51746 /* Marshal.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C31CEBACD5005A5DEA /* Marshal.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 63 | CC3023451CF9616700B51746 /* Mapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C11CEBACD0005A5DEA /* Mapper.framework */; }; 64 | CC3023461CF9616700B51746 /* Mapper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C11CEBACD0005A5DEA /* Mapper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 65 | CC30234A1CF9692700B51746 /* Mapper_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3023471CF9692700B51746 /* Mapper_Tests.swift */; }; 66 | CC30234B1CF9692700B51746 /* Marshal_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3023481CF9692700B51746 /* Marshal_Tests.swift */; }; 67 | CC30234C1CF9692700B51746 /* Unbox_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3023491CF9692700B51746 /* Unbox_Tests.swift */; }; 68 | CC5A1A021CEADE59007238F3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC5A1A011CEADE59007238F3 /* AppDelegate.swift */; }; 69 | CC5A1A041CEADE59007238F3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC5A1A031CEADE59007238F3 /* ViewController.swift */; }; 70 | CC5A1A071CEADE59007238F3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CC5A1A051CEADE59007238F3 /* Main.storyboard */; }; 71 | CC5A1A091CEADE59007238F3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC5A1A081CEADE59007238F3 /* Assets.xcassets */; }; 72 | CC5A1A0C1CEADE59007238F3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CC5A1A0A1CEADE59007238F3 /* LaunchScreen.storyboard */; }; 73 | CC5A1A4D1CEAE182007238F3 /* Large.json in Resources */ = {isa = PBXBuildFile; fileRef = CC5A1A4C1CEAE182007238F3 /* Large.json */; }; 74 | CC7A7FB71DC053E400A69A0B /* Decodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BA72EC71DBECA48007ADBAE /* Decodable.framework */; }; 75 | CC7A7FB81DC053E400A69A0B /* Decodable.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5BA72EC71DBECA48007ADBAE /* Decodable.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 76 | CC9786A11CEBABE7005A5DEA /* ModelObjects.h in Headers */ = {isa = PBXBuildFile; fileRef = CC9786A01CEBABE7005A5DEA /* ModelObjects.h */; settings = {ATTRIBUTES = (Public, ); }; }; 77 | CC9786B31CEBABE7005A5DEA /* ModelObjects.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC97869E1CEBABE7005A5DEA /* ModelObjects.framework */; }; 78 | CC9786B41CEBABE7005A5DEA /* ModelObjects.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CC97869E1CEBABE7005A5DEA /* ModelObjects.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 79 | CC9786BC1CEBAC14005A5DEA /* Recording.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC9786BB1CEBAC14005A5DEA /* Recording.swift */; }; 80 | CC9786BE1CEBAC21005A5DEA /* Program.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC9786BD1CEBAC21005A5DEA /* Program.swift */; }; 81 | CC9786C01CEBAC6C005A5DEA /* NSDate+JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC9786BF1CEBAC6C005A5DEA /* NSDate+JSON.swift */; }; 82 | CC9786C21CEBACD0005A5DEA /* Mapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C11CEBACD0005A5DEA /* Mapper.framework */; }; 83 | CC9786C41CEBACD5005A5DEA /* Marshal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C31CEBACD5005A5DEA /* Marshal.framework */; }; 84 | CC9786C61CEBACE8005A5DEA /* Unbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC9786C51CEBACE8005A5DEA /* Unbox.framework */; }; 85 | CCD510591CFFFB4C00E9C0D1 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCD510581CFFFB4C00E9C0D1 /* SwiftyJSON.framework */; }; 86 | CCD5105B1CFFFF7000E9C0D1 /* SwiftyJSON_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCD5105A1CFFFF7000E9C0D1 /* SwiftyJSON_Tests.swift */; }; 87 | CCFD5B551D0A718C0021C2B3 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCD510581CFFFB4C00E9C0D1 /* SwiftyJSON.framework */; }; 88 | CCFD5B571D0A71990021C2B3 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CCD510581CFFFB4C00E9C0D1 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 89 | /* End PBXBuildFile section */ 90 | 91 | /* Begin PBXContainerItemProxy section */ 92 | CC5A1A131CEADE59007238F3 /* PBXContainerItemProxy */ = { 93 | isa = PBXContainerItemProxy; 94 | containerPortal = CC5A19F61CEADE59007238F3 /* Project object */; 95 | proxyType = 1; 96 | remoteGlobalIDString = CC5A19FD1CEADE59007238F3; 97 | remoteInfo = JSONShootout; 98 | }; 99 | CC9786B11CEBABE7005A5DEA /* PBXContainerItemProxy */ = { 100 | isa = PBXContainerItemProxy; 101 | containerPortal = CC5A19F61CEADE59007238F3 /* Project object */; 102 | proxyType = 1; 103 | remoteGlobalIDString = CC97869D1CEBABE7005A5DEA; 104 | remoteInfo = ModelObjects; 105 | }; 106 | /* End PBXContainerItemProxy section */ 107 | 108 | /* Begin PBXCopyFilesBuildPhase section */ 109 | CC5A1A421CEADFB8007238F3 /* Embed Frameworks */ = { 110 | isa = PBXCopyFilesBuildPhase; 111 | buildActionMask = 2147483647; 112 | dstPath = ""; 113 | dstSubfolderSpec = 10; 114 | files = ( 115 | CC7A7FB81DC053E400A69A0B /* Decodable.framework in Embed Frameworks */, 116 | 2098D54B1DC1F5E800A15075 /* Genome.framework in Embed Frameworks */, 117 | 681299071DBFFCBC009960BE /* ObjectMapper.framework in Embed Frameworks */, 118 | CC3023441CF9616600B51746 /* Marshal.framework in Embed Frameworks */, 119 | CC3023461CF9616700B51746 /* Mapper.framework in Embed Frameworks */, 120 | AA2B38CC1DC0B4AE008CECCD /* JSON.framework in Embed Frameworks */, 121 | CC9786B41CEBABE7005A5DEA /* ModelObjects.framework in Embed Frameworks */, 122 | CC3023421CF9616600B51746 /* Unbox.framework in Embed Frameworks */, 123 | CCFD5B571D0A71990021C2B3 /* SwiftyJSON.framework in Embed Frameworks */, 124 | 716A8A9B1DC1D10A00BF314B /* Gloss.framework in Embed Frameworks */, 125 | 2F28689A1DE7F502002A6F68 /* Freddy.framework in Embed Frameworks */, 126 | ); 127 | name = "Embed Frameworks"; 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXCopyFilesBuildPhase section */ 131 | 132 | /* Begin PBXFileReference section */ 133 | 2098D5491DC1F5E800A15075 /* Genome.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Genome.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 134 | 20A0B9561DC2584D001D8A14 /* Recording+Genome.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Genome.swift"; sourceTree = ""; }; 135 | 20A0B9581DC25B60001D8A14 /* Program+Genome.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Genome.swift"; sourceTree = ""; }; 136 | 20A0B95A1DC25F03001D8A14 /* Genome_Test.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Genome_Test.swift; sourceTree = ""; }; 137 | 20A0B9691DC26803001D8A14 /* GenomeFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GenomeFoundation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 138 | 2F2868951DE7F34B002A6F68 /* Freddy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Freddy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 139 | 2F2868971DE7F48A002A6F68 /* Freddy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Freddy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 140 | 2F28689B1DE7F66F002A6F68 /* Freddy_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Freddy_Tests.swift; sourceTree = ""; }; 141 | 2F28689D1DE7FB58002A6F68 /* Program+Freddy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Freddy.swift"; sourceTree = ""; }; 142 | 2F28689F1DE8843C002A6F68 /* Recording+Freddy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Freddy.swift"; sourceTree = ""; }; 143 | 5B69A1D91DBEC84200B12579 /* Recording+Decodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Decodable.swift"; sourceTree = ""; }; 144 | 5B69A1DB1DBEC86A00B12579 /* Program+Decodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Decodable.swift"; sourceTree = ""; }; 145 | 5B69A1DD1DBEC9A400B12579 /* Decodable_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decodable_Tests.swift; sourceTree = ""; }; 146 | 5BA72EC71DBECA48007ADBAE /* Decodable.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Decodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 147 | 681299041DBFFCAB009960BE /* ObjectMapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ObjectMapper.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 148 | 681299171DC00DB1009960BE /* ObjectMapper_Test.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectMapper_Test.swift; sourceTree = ""; }; 149 | 681299191DC00DBB009960BE /* Program+ObjectMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+ObjectMapper.swift"; sourceTree = ""; }; 150 | 6812991A1DC00DBB009960BE /* Recording+ObjectMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+ObjectMapper.swift"; sourceTree = ""; }; 151 | 71337C8A1DBEBC6B00DCA374 /* Recording+Marshal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Marshal.swift"; sourceTree = ""; }; 152 | 71337C8C1DBEBC7900DCA374 /* Recording+Mapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Mapper.swift"; sourceTree = ""; }; 153 | 71337C8E1DBEBC8600DCA374 /* Recording+Unbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Unbox.swift"; sourceTree = ""; }; 154 | 71337C901DBEBCA300DCA374 /* Recording+SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+SwiftyJSON.swift"; sourceTree = ""; }; 155 | 71337C921DBEBFB400DCA374 /* Program+Marshal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Marshal.swift"; sourceTree = ""; }; 156 | 71337C941DBEBFC300DCA374 /* Program+Mapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Mapper.swift"; sourceTree = ""; }; 157 | 71337C961DBEBFD000DCA374 /* Program+Unbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Unbox.swift"; sourceTree = ""; }; 158 | 71337C981DBEBFDC00DCA374 /* Program+SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+SwiftyJSON.swift"; sourceTree = ""; }; 159 | 716A8A971DC1D0E900BF314B /* Gloss.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Gloss.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 160 | 716A8A9C1DC1D18B00BF314B /* JSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 161 | 7C3FCD2D1DC1B19E00C82DEE /* Gloss.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Gloss.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 162 | 7C3FCD301DC1B2A100C82DEE /* Program+Gloss.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+Gloss.swift"; sourceTree = ""; }; 163 | 7C3FCD321DC1B2AE00C82DEE /* Recording+Gloss.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+Gloss.swift"; sourceTree = ""; }; 164 | 7C3FCD341DC1B61600C82DEE /* Gloss_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Gloss_Tests.swift; sourceTree = ""; }; 165 | 9E9BF9C71DCD116900548161 /* PMJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PMJSON.framework; path = Carthage/Checkouts/PMJSON/build/Debug/PMJSON.framework; sourceTree = ""; }; 166 | 9E9BF9C91DCD117300548161 /* PMJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PMJSON.framework; path = Carthage/Checkouts/PMJSON/build/Debug/PMJSON.framework; sourceTree = ""; }; 167 | 9E9BF9CB1DCD11BA00548161 /* PMJSON_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PMJSON_Tests.swift; sourceTree = ""; }; 168 | 9E9BF9CD1DCD126D00548161 /* Program+PMJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Program+PMJSON.swift"; sourceTree = ""; }; 169 | 9E9BF9CF1DCD307200548161 /* Recording+PMJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+PMJSON.swift"; sourceTree = ""; }; 170 | AA2B38CA1DC0B4AE008CECCD /* JSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 171 | AA2B38CD1DC0B4CC008CECCD /* Program+JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = "Program+JSON.swift"; sourceTree = ""; tabWidth = 4; }; 172 | AA2B38D11DC0B57F008CECCD /* Recording+JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Recording+JSON.swift"; sourceTree = ""; }; 173 | AA2B38D31DC0B6D3008CECCD /* JSON_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON_Tests.swift; sourceTree = ""; }; 174 | CC3023471CF9692700B51746 /* Mapper_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mapper_Tests.swift; sourceTree = ""; }; 175 | CC3023481CF9692700B51746 /* Marshal_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Marshal_Tests.swift; sourceTree = ""; }; 176 | CC3023491CF9692700B51746 /* Unbox_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Unbox_Tests.swift; sourceTree = ""; }; 177 | CC5A19FE1CEADE59007238F3 /* JSONShootout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSONShootout.app; sourceTree = BUILT_PRODUCTS_DIR; }; 178 | CC5A1A011CEADE59007238F3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 179 | CC5A1A031CEADE59007238F3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 180 | CC5A1A061CEADE59007238F3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 181 | CC5A1A081CEADE59007238F3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 182 | CC5A1A0B1CEADE59007238F3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 183 | CC5A1A0D1CEADE59007238F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 184 | CC5A1A121CEADE59007238F3 /* JSONShootoutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSONShootoutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 185 | CC5A1A181CEADE59007238F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 186 | CC5A1A4C1CEAE182007238F3 /* Large.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Large.json; sourceTree = ""; }; 187 | CC97869E1CEBABE7005A5DEA /* ModelObjects.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ModelObjects.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 188 | CC9786A01CEBABE7005A5DEA /* ModelObjects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ModelObjects.h; sourceTree = ""; }; 189 | CC9786A21CEBABE7005A5DEA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 190 | CC9786BB1CEBAC14005A5DEA /* Recording.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Recording.swift; sourceTree = ""; }; 191 | CC9786BD1CEBAC21005A5DEA /* Program.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Program.swift; sourceTree = ""; }; 192 | CC9786BF1CEBAC6C005A5DEA /* NSDate+JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSDate+JSON.swift"; sourceTree = ""; }; 193 | CC9786C11CEBACD0005A5DEA /* Mapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapper.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 194 | CC9786C31CEBACD5005A5DEA /* Marshal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Marshal.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 195 | CC9786C51CEBACE8005A5DEA /* Unbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Unbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 196 | CCD510581CFFFB4C00E9C0D1 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 197 | CCD5105A1CFFFF7000E9C0D1 /* SwiftyJSON_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyJSON_Tests.swift; sourceTree = ""; }; 198 | /* End PBXFileReference section */ 199 | 200 | /* Begin PBXFrameworksBuildPhase section */ 201 | CC5A19FB1CEADE59007238F3 /* Frameworks */ = { 202 | isa = PBXFrameworksBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 2F2868981DE7F48A002A6F68 /* Freddy.framework in Frameworks */, 206 | 20A0B96B1DC26810001D8A14 /* GenomeFoundation.framework in Frameworks */, 207 | 2098D54A1DC1F5E800A15075 /* Genome.framework in Frameworks */, 208 | 681299051DBFFCAB009960BE /* ObjectMapper.framework in Frameworks */, 209 | CCFD5B551D0A718C0021C2B3 /* SwiftyJSON.framework in Frameworks */, 210 | 716A8A9A1DC1D10A00BF314B /* Gloss.framework in Frameworks */, 211 | CC7A7FB71DC053E400A69A0B /* Decodable.framework in Frameworks */, 212 | CC3023431CF9616600B51746 /* Marshal.framework in Frameworks */, 213 | AA2B38CB1DC0B4AE008CECCD /* JSON.framework in Frameworks */, 214 | CC3023451CF9616700B51746 /* Mapper.framework in Frameworks */, 215 | CC9786B31CEBABE7005A5DEA /* ModelObjects.framework in Frameworks */, 216 | CC3023411CF9616600B51746 /* Unbox.framework in Frameworks */, 217 | 9E9BF9CA1DCD117300548161 /* PMJSON.framework in Frameworks */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | CC5A1A0F1CEADE59007238F3 /* Frameworks */ = { 222 | isa = PBXFrameworksBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 5BA72ECF1DBECC0C007ADBAE /* ModelObjects.framework in Frameworks */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | CC97869A1CEBABE7005A5DEA /* Frameworks */ = { 230 | isa = PBXFrameworksBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 2F2868961DE7F34B002A6F68 /* Freddy.framework in Frameworks */, 234 | 2098D54C1DC1F5FB00A15075 /* Genome.framework in Frameworks */, 235 | 716A8A9D1DC1D18B00BF314B /* JSON.framework in Frameworks */, 236 | 716A8A981DC1D0E900BF314B /* Gloss.framework in Frameworks */, 237 | CCD510591CFFFB4C00E9C0D1 /* SwiftyJSON.framework in Frameworks */, 238 | CC9786C61CEBACE8005A5DEA /* Unbox.framework in Frameworks */, 239 | 681299061DBFFCAB009960BE /* ObjectMapper.framework in Frameworks */, 240 | CC9786C41CEBACD5005A5DEA /* Marshal.framework in Frameworks */, 241 | CC9786C21CEBACD0005A5DEA /* Mapper.framework in Frameworks */, 242 | 5BA72ED31DBECD52007ADBAE /* Decodable.framework in Frameworks */, 243 | 9E9BF9C81DCD116900548161 /* PMJSON.framework in Frameworks */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | /* End PBXFrameworksBuildPhase section */ 248 | 249 | /* Begin PBXGroup section */ 250 | 7C3FCD281DC1B16100C82DEE /* Frameworks */ = { 251 | isa = PBXGroup; 252 | children = ( 253 | 2F2868971DE7F48A002A6F68 /* Freddy.framework */, 254 | 2F2868951DE7F34B002A6F68 /* Freddy.framework */, 255 | 9E9BF9C91DCD117300548161 /* PMJSON.framework */, 256 | 9E9BF9C71DCD116900548161 /* PMJSON.framework */, 257 | 2098D5491DC1F5E800A15075 /* Genome.framework */, 258 | 7C3FCD2D1DC1B19E00C82DEE /* Gloss.framework */, 259 | AA2B38CA1DC0B4AE008CECCD /* JSON.framework */, 260 | 5BA72EC71DBECA48007ADBAE /* Decodable.framework */, 261 | CCD510581CFFFB4C00E9C0D1 /* SwiftyJSON.framework */, 262 | 20A0B9691DC26803001D8A14 /* GenomeFoundation.framework */, 263 | 681299041DBFFCAB009960BE /* ObjectMapper.framework */, 264 | CC9786C51CEBACE8005A5DEA /* Unbox.framework */, 265 | CC9786C31CEBACD5005A5DEA /* Marshal.framework */, 266 | CC9786C11CEBACD0005A5DEA /* Mapper.framework */, 267 | 716A8A9C1DC1D18B00BF314B /* JSON.framework */, 268 | 716A8A971DC1D0E900BF314B /* Gloss.framework */, 269 | ); 270 | name = Frameworks; 271 | sourceTree = ""; 272 | }; 273 | CC5A19F51CEADE59007238F3 = { 274 | isa = PBXGroup; 275 | children = ( 276 | CC5A1A001CEADE59007238F3 /* JSONShootout */, 277 | CC5A1A151CEADE59007238F3 /* JSONShootoutTests */, 278 | CC97869F1CEBABE7005A5DEA /* ModelObjects */, 279 | CC5A19FF1CEADE59007238F3 /* Products */, 280 | 7C3FCD281DC1B16100C82DEE /* Frameworks */, 281 | ); 282 | sourceTree = ""; 283 | }; 284 | CC5A19FF1CEADE59007238F3 /* Products */ = { 285 | isa = PBXGroup; 286 | children = ( 287 | CC5A19FE1CEADE59007238F3 /* JSONShootout.app */, 288 | CC5A1A121CEADE59007238F3 /* JSONShootoutTests.xctest */, 289 | CC97869E1CEBABE7005A5DEA /* ModelObjects.framework */, 290 | ); 291 | name = Products; 292 | sourceTree = ""; 293 | }; 294 | CC5A1A001CEADE59007238F3 /* JSONShootout */ = { 295 | isa = PBXGroup; 296 | children = ( 297 | CC5A1A011CEADE59007238F3 /* AppDelegate.swift */, 298 | CC5A1A031CEADE59007238F3 /* ViewController.swift */, 299 | CC5A1A051CEADE59007238F3 /* Main.storyboard */, 300 | CC5A1A081CEADE59007238F3 /* Assets.xcassets */, 301 | CC5A1A0A1CEADE59007238F3 /* LaunchScreen.storyboard */, 302 | CC5A1A0D1CEADE59007238F3 /* Info.plist */, 303 | ); 304 | path = JSONShootout; 305 | sourceTree = ""; 306 | }; 307 | CC5A1A151CEADE59007238F3 /* JSONShootoutTests */ = { 308 | isa = PBXGroup; 309 | children = ( 310 | 5B69A1DD1DBEC9A400B12579 /* Decodable_Tests.swift */, 311 | CC3023471CF9692700B51746 /* Mapper_Tests.swift */, 312 | CC3023481CF9692700B51746 /* Marshal_Tests.swift */, 313 | 7C3FCD341DC1B61600C82DEE /* Gloss_Tests.swift */, 314 | 20A0B95A1DC25F03001D8A14 /* Genome_Test.swift */, 315 | CCD5105A1CFFFF7000E9C0D1 /* SwiftyJSON_Tests.swift */, 316 | 681299171DC00DB1009960BE /* ObjectMapper_Test.swift */, 317 | CC3023491CF9692700B51746 /* Unbox_Tests.swift */, 318 | AA2B38D31DC0B6D3008CECCD /* JSON_Tests.swift */, 319 | 9E9BF9CB1DCD11BA00548161 /* PMJSON_Tests.swift */, 320 | 2F28689B1DE7F66F002A6F68 /* Freddy_Tests.swift */, 321 | CC5A1A4C1CEAE182007238F3 /* Large.json */, 322 | CC5A1A181CEADE59007238F3 /* Info.plist */, 323 | ); 324 | path = JSONShootoutTests; 325 | sourceTree = ""; 326 | }; 327 | CC97869F1CEBABE7005A5DEA /* ModelObjects */ = { 328 | isa = PBXGroup; 329 | children = ( 330 | CC9786A01CEBABE7005A5DEA /* ModelObjects.h */, 331 | CC9786A21CEBABE7005A5DEA /* Info.plist */, 332 | CC9786BB1CEBAC14005A5DEA /* Recording.swift */, 333 | CC9786BD1CEBAC21005A5DEA /* Program.swift */, 334 | CC9786BF1CEBAC6C005A5DEA /* NSDate+JSON.swift */, 335 | 71337C8A1DBEBC6B00DCA374 /* Recording+Marshal.swift */, 336 | 71337C8C1DBEBC7900DCA374 /* Recording+Mapper.swift */, 337 | 71337C8E1DBEBC8600DCA374 /* Recording+Unbox.swift */, 338 | 71337C901DBEBCA300DCA374 /* Recording+SwiftyJSON.swift */, 339 | 5B69A1D91DBEC84200B12579 /* Recording+Decodable.swift */, 340 | 6812991A1DC00DBB009960BE /* Recording+ObjectMapper.swift */, 341 | AA2B38D11DC0B57F008CECCD /* Recording+JSON.swift */, 342 | 7C3FCD321DC1B2AE00C82DEE /* Recording+Gloss.swift */, 343 | 20A0B9561DC2584D001D8A14 /* Recording+Genome.swift */, 344 | 9E9BF9CF1DCD307200548161 /* Recording+PMJSON.swift */, 345 | 2F28689F1DE8843C002A6F68 /* Recording+Freddy.swift */, 346 | 71337C921DBEBFB400DCA374 /* Program+Marshal.swift */, 347 | 71337C941DBEBFC300DCA374 /* Program+Mapper.swift */, 348 | 71337C961DBEBFD000DCA374 /* Program+Unbox.swift */, 349 | 71337C981DBEBFDC00DCA374 /* Program+SwiftyJSON.swift */, 350 | 5B69A1DB1DBEC86A00B12579 /* Program+Decodable.swift */, 351 | 681299191DC00DBB009960BE /* Program+ObjectMapper.swift */, 352 | AA2B38CD1DC0B4CC008CECCD /* Program+JSON.swift */, 353 | 7C3FCD301DC1B2A100C82DEE /* Program+Gloss.swift */, 354 | 20A0B9581DC25B60001D8A14 /* Program+Genome.swift */, 355 | 9E9BF9CD1DCD126D00548161 /* Program+PMJSON.swift */, 356 | 2F28689D1DE7FB58002A6F68 /* Program+Freddy.swift */, 357 | ); 358 | path = ModelObjects; 359 | sourceTree = ""; 360 | }; 361 | /* End PBXGroup section */ 362 | 363 | /* Begin PBXHeadersBuildPhase section */ 364 | CC97869B1CEBABE7005A5DEA /* Headers */ = { 365 | isa = PBXHeadersBuildPhase; 366 | buildActionMask = 2147483647; 367 | files = ( 368 | CC9786A11CEBABE7005A5DEA /* ModelObjects.h in Headers */, 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | /* End PBXHeadersBuildPhase section */ 373 | 374 | /* Begin PBXNativeTarget section */ 375 | CC5A19FD1CEADE59007238F3 /* JSONShootout */ = { 376 | isa = PBXNativeTarget; 377 | buildConfigurationList = CC5A1A1B1CEADE59007238F3 /* Build configuration list for PBXNativeTarget "JSONShootout" */; 378 | buildPhases = ( 379 | CC5A19FA1CEADE59007238F3 /* Sources */, 380 | CC5A19FB1CEADE59007238F3 /* Frameworks */, 381 | CC5A19FC1CEADE59007238F3 /* Resources */, 382 | CC5A1A421CEADFB8007238F3 /* Embed Frameworks */, 383 | ); 384 | buildRules = ( 385 | ); 386 | dependencies = ( 387 | CC9786B21CEBABE7005A5DEA /* PBXTargetDependency */, 388 | ); 389 | name = JSONShootout; 390 | productName = JSONShootout; 391 | productReference = CC5A19FE1CEADE59007238F3 /* JSONShootout.app */; 392 | productType = "com.apple.product-type.application"; 393 | }; 394 | CC5A1A111CEADE59007238F3 /* JSONShootoutTests */ = { 395 | isa = PBXNativeTarget; 396 | buildConfigurationList = CC5A1A1E1CEADE59007238F3 /* Build configuration list for PBXNativeTarget "JSONShootoutTests" */; 397 | buildPhases = ( 398 | CC5A1A0E1CEADE59007238F3 /* Sources */, 399 | CC5A1A0F1CEADE59007238F3 /* Frameworks */, 400 | CC5A1A101CEADE59007238F3 /* Resources */, 401 | ); 402 | buildRules = ( 403 | ); 404 | dependencies = ( 405 | CC5A1A141CEADE59007238F3 /* PBXTargetDependency */, 406 | ); 407 | name = JSONShootoutTests; 408 | productName = JSONShootoutTests; 409 | productReference = CC5A1A121CEADE59007238F3 /* JSONShootoutTests.xctest */; 410 | productType = "com.apple.product-type.bundle.unit-test"; 411 | }; 412 | CC97869D1CEBABE7005A5DEA /* ModelObjects */ = { 413 | isa = PBXNativeTarget; 414 | buildConfigurationList = CC9786B91CEBABE7005A5DEA /* Build configuration list for PBXNativeTarget "ModelObjects" */; 415 | buildPhases = ( 416 | CC9786991CEBABE7005A5DEA /* Sources */, 417 | CC97869A1CEBABE7005A5DEA /* Frameworks */, 418 | CC97869B1CEBABE7005A5DEA /* Headers */, 419 | CC97869C1CEBABE7005A5DEA /* Resources */, 420 | ); 421 | buildRules = ( 422 | ); 423 | dependencies = ( 424 | ); 425 | name = ModelObjects; 426 | productName = ModelObjects; 427 | productReference = CC97869E1CEBABE7005A5DEA /* ModelObjects.framework */; 428 | productType = "com.apple.product-type.framework"; 429 | }; 430 | /* End PBXNativeTarget section */ 431 | 432 | /* Begin PBXProject section */ 433 | CC5A19F61CEADE59007238F3 /* Project object */ = { 434 | isa = PBXProject; 435 | attributes = { 436 | LastSwiftUpdateCheck = 0730; 437 | LastUpgradeCheck = 0800; 438 | ORGANIZATIONNAME = SwiftBit; 439 | TargetAttributes = { 440 | CC5A19FD1CEADE59007238F3 = { 441 | CreatedOnToolsVersion = 7.3.1; 442 | LastSwiftMigration = 0800; 443 | }; 444 | CC5A1A111CEADE59007238F3 = { 445 | CreatedOnToolsVersion = 7.3.1; 446 | LastSwiftMigration = 0800; 447 | TestTargetID = CC5A19FD1CEADE59007238F3; 448 | }; 449 | CC97869D1CEBABE7005A5DEA = { 450 | CreatedOnToolsVersion = 7.3.1; 451 | LastSwiftMigration = 0800; 452 | }; 453 | }; 454 | }; 455 | buildConfigurationList = CC5A19F91CEADE59007238F3 /* Build configuration list for PBXProject "JSONShootout" */; 456 | compatibilityVersion = "Xcode 3.2"; 457 | developmentRegion = English; 458 | hasScannedForEncodings = 0; 459 | knownRegions = ( 460 | en, 461 | Base, 462 | ); 463 | mainGroup = CC5A19F51CEADE59007238F3; 464 | productRefGroup = CC5A19FF1CEADE59007238F3 /* Products */; 465 | projectDirPath = ""; 466 | projectRoot = ""; 467 | targets = ( 468 | CC5A19FD1CEADE59007238F3 /* JSONShootout */, 469 | CC5A1A111CEADE59007238F3 /* JSONShootoutTests */, 470 | CC97869D1CEBABE7005A5DEA /* ModelObjects */, 471 | ); 472 | }; 473 | /* End PBXProject section */ 474 | 475 | /* Begin PBXResourcesBuildPhase section */ 476 | CC5A19FC1CEADE59007238F3 /* Resources */ = { 477 | isa = PBXResourcesBuildPhase; 478 | buildActionMask = 2147483647; 479 | files = ( 480 | CC5A1A0C1CEADE59007238F3 /* LaunchScreen.storyboard in Resources */, 481 | CC5A1A091CEADE59007238F3 /* Assets.xcassets in Resources */, 482 | CC5A1A071CEADE59007238F3 /* Main.storyboard in Resources */, 483 | ); 484 | runOnlyForDeploymentPostprocessing = 0; 485 | }; 486 | CC5A1A101CEADE59007238F3 /* Resources */ = { 487 | isa = PBXResourcesBuildPhase; 488 | buildActionMask = 2147483647; 489 | files = ( 490 | CC5A1A4D1CEAE182007238F3 /* Large.json in Resources */, 491 | ); 492 | runOnlyForDeploymentPostprocessing = 0; 493 | }; 494 | CC97869C1CEBABE7005A5DEA /* Resources */ = { 495 | isa = PBXResourcesBuildPhase; 496 | buildActionMask = 2147483647; 497 | files = ( 498 | ); 499 | runOnlyForDeploymentPostprocessing = 0; 500 | }; 501 | /* End PBXResourcesBuildPhase section */ 502 | 503 | /* Begin PBXSourcesBuildPhase section */ 504 | CC5A19FA1CEADE59007238F3 /* Sources */ = { 505 | isa = PBXSourcesBuildPhase; 506 | buildActionMask = 2147483647; 507 | files = ( 508 | CC5A1A041CEADE59007238F3 /* ViewController.swift in Sources */, 509 | CC5A1A021CEADE59007238F3 /* AppDelegate.swift in Sources */, 510 | ); 511 | runOnlyForDeploymentPostprocessing = 0; 512 | }; 513 | CC5A1A0E1CEADE59007238F3 /* Sources */ = { 514 | isa = PBXSourcesBuildPhase; 515 | buildActionMask = 2147483647; 516 | files = ( 517 | CC30234B1CF9692700B51746 /* Marshal_Tests.swift in Sources */, 518 | 20A0B95B1DC25F03001D8A14 /* Genome_Test.swift in Sources */, 519 | CC30234A1CF9692700B51746 /* Mapper_Tests.swift in Sources */, 520 | CC30234C1CF9692700B51746 /* Unbox_Tests.swift in Sources */, 521 | AA2B38D41DC0B6D3008CECCD /* JSON_Tests.swift in Sources */, 522 | 2F28689C1DE7F66F002A6F68 /* Freddy_Tests.swift in Sources */, 523 | 5B69A1DE1DBEC9A400B12579 /* Decodable_Tests.swift in Sources */, 524 | CCD5105B1CFFFF7000E9C0D1 /* SwiftyJSON_Tests.swift in Sources */, 525 | 7C3FCD351DC1B61600C82DEE /* Gloss_Tests.swift in Sources */, 526 | 9E9BF9CC1DCD11BA00548161 /* PMJSON_Tests.swift in Sources */, 527 | 681299181DC00DB1009960BE /* ObjectMapper_Test.swift in Sources */, 528 | ); 529 | runOnlyForDeploymentPostprocessing = 0; 530 | }; 531 | CC9786991CEBABE7005A5DEA /* Sources */ = { 532 | isa = PBXSourcesBuildPhase; 533 | buildActionMask = 2147483647; 534 | files = ( 535 | 2F2868A01DE8843C002A6F68 /* Recording+Freddy.swift in Sources */, 536 | 71337C8F1DBEBC8600DCA374 /* Recording+Unbox.swift in Sources */, 537 | 6812991C1DC00DBB009960BE /* Recording+ObjectMapper.swift in Sources */, 538 | 71337C971DBEBFD000DCA374 /* Program+Unbox.swift in Sources */, 539 | CC9786BE1CEBAC21005A5DEA /* Program.swift in Sources */, 540 | 71337C8D1DBEBC7900DCA374 /* Recording+Mapper.swift in Sources */, 541 | 6812991B1DC00DBB009960BE /* Program+ObjectMapper.swift in Sources */, 542 | 9E9BF9D01DCD307200548161 /* Recording+PMJSON.swift in Sources */, 543 | 71337C991DBEBFDC00DCA374 /* Program+SwiftyJSON.swift in Sources */, 544 | 2F28689E1DE7FB58002A6F68 /* Program+Freddy.swift in Sources */, 545 | 71337C931DBEBFB400DCA374 /* Program+Marshal.swift in Sources */, 546 | CC9786C01CEBAC6C005A5DEA /* NSDate+JSON.swift in Sources */, 547 | 9E9BF9CE1DCD126D00548161 /* Program+PMJSON.swift in Sources */, 548 | 5B69A1DA1DBEC84200B12579 /* Recording+Decodable.swift in Sources */, 549 | AA2B38D01DC0B4D2008CECCD /* Program+JSON.swift in Sources */, 550 | 7C3FCD311DC1B2A100C82DEE /* Program+Gloss.swift in Sources */, 551 | 5B69A1DC1DBEC86A00B12579 /* Program+Decodable.swift in Sources */, 552 | 7C3FCD331DC1B2AE00C82DEE /* Recording+Gloss.swift in Sources */, 553 | AA2B38D21DC0B57F008CECCD /* Recording+JSON.swift in Sources */, 554 | 71337C911DBEBCA300DCA374 /* Recording+SwiftyJSON.swift in Sources */, 555 | 20A0B9571DC2584D001D8A14 /* Recording+Genome.swift in Sources */, 556 | 71337C951DBEBFC300DCA374 /* Program+Mapper.swift in Sources */, 557 | 71337C8B1DBEBC6B00DCA374 /* Recording+Marshal.swift in Sources */, 558 | 20A0B9591DC25B60001D8A14 /* Program+Genome.swift in Sources */, 559 | CC9786BC1CEBAC14005A5DEA /* Recording.swift in Sources */, 560 | ); 561 | runOnlyForDeploymentPostprocessing = 0; 562 | }; 563 | /* End PBXSourcesBuildPhase section */ 564 | 565 | /* Begin PBXTargetDependency section */ 566 | CC5A1A141CEADE59007238F3 /* PBXTargetDependency */ = { 567 | isa = PBXTargetDependency; 568 | target = CC5A19FD1CEADE59007238F3 /* JSONShootout */; 569 | targetProxy = CC5A1A131CEADE59007238F3 /* PBXContainerItemProxy */; 570 | }; 571 | CC9786B21CEBABE7005A5DEA /* PBXTargetDependency */ = { 572 | isa = PBXTargetDependency; 573 | target = CC97869D1CEBABE7005A5DEA /* ModelObjects */; 574 | targetProxy = CC9786B11CEBABE7005A5DEA /* PBXContainerItemProxy */; 575 | }; 576 | /* End PBXTargetDependency section */ 577 | 578 | /* Begin PBXVariantGroup section */ 579 | CC5A1A051CEADE59007238F3 /* Main.storyboard */ = { 580 | isa = PBXVariantGroup; 581 | children = ( 582 | CC5A1A061CEADE59007238F3 /* Base */, 583 | ); 584 | name = Main.storyboard; 585 | sourceTree = ""; 586 | }; 587 | CC5A1A0A1CEADE59007238F3 /* LaunchScreen.storyboard */ = { 588 | isa = PBXVariantGroup; 589 | children = ( 590 | CC5A1A0B1CEADE59007238F3 /* Base */, 591 | ); 592 | name = LaunchScreen.storyboard; 593 | sourceTree = ""; 594 | }; 595 | /* End PBXVariantGroup section */ 596 | 597 | /* Begin XCBuildConfiguration section */ 598 | CC5A1A191CEADE59007238F3 /* Debug */ = { 599 | isa = XCBuildConfiguration; 600 | buildSettings = { 601 | ALWAYS_SEARCH_USER_PATHS = NO; 602 | CLANG_ANALYZER_NONNULL = YES; 603 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 604 | CLANG_CXX_LIBRARY = "libc++"; 605 | CLANG_ENABLE_MODULES = YES; 606 | CLANG_ENABLE_OBJC_ARC = YES; 607 | CLANG_WARN_BOOL_CONVERSION = YES; 608 | CLANG_WARN_CONSTANT_CONVERSION = YES; 609 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 610 | CLANG_WARN_EMPTY_BODY = YES; 611 | CLANG_WARN_ENUM_CONVERSION = YES; 612 | CLANG_WARN_INFINITE_RECURSION = YES; 613 | CLANG_WARN_INT_CONVERSION = YES; 614 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 615 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 616 | CLANG_WARN_UNREACHABLE_CODE = YES; 617 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 618 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 619 | COPY_PHASE_STRIP = NO; 620 | DEBUG_INFORMATION_FORMAT = dwarf; 621 | ENABLE_STRICT_OBJC_MSGSEND = YES; 622 | ENABLE_TESTABILITY = YES; 623 | GCC_C_LANGUAGE_STANDARD = gnu99; 624 | GCC_DYNAMIC_NO_PIC = NO; 625 | GCC_NO_COMMON_BLOCKS = YES; 626 | GCC_OPTIMIZATION_LEVEL = 0; 627 | GCC_PREPROCESSOR_DEFINITIONS = ( 628 | "DEBUG=1", 629 | "$(inherited)", 630 | ); 631 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 632 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 633 | GCC_WARN_UNDECLARED_SELECTOR = YES; 634 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 635 | GCC_WARN_UNUSED_FUNCTION = YES; 636 | GCC_WARN_UNUSED_VARIABLE = YES; 637 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 638 | MTL_ENABLE_DEBUG_INFO = YES; 639 | ONLY_ACTIVE_ARCH = YES; 640 | SDKROOT = iphoneos; 641 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 642 | }; 643 | name = Debug; 644 | }; 645 | CC5A1A1A1CEADE59007238F3 /* Release */ = { 646 | isa = XCBuildConfiguration; 647 | buildSettings = { 648 | ALWAYS_SEARCH_USER_PATHS = NO; 649 | CLANG_ANALYZER_NONNULL = YES; 650 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 651 | CLANG_CXX_LIBRARY = "libc++"; 652 | CLANG_ENABLE_MODULES = YES; 653 | CLANG_ENABLE_OBJC_ARC = YES; 654 | CLANG_WARN_BOOL_CONVERSION = YES; 655 | CLANG_WARN_CONSTANT_CONVERSION = YES; 656 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 657 | CLANG_WARN_EMPTY_BODY = YES; 658 | CLANG_WARN_ENUM_CONVERSION = YES; 659 | CLANG_WARN_INFINITE_RECURSION = YES; 660 | CLANG_WARN_INT_CONVERSION = YES; 661 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 662 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 663 | CLANG_WARN_UNREACHABLE_CODE = YES; 664 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 665 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 666 | COPY_PHASE_STRIP = NO; 667 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 668 | ENABLE_NS_ASSERTIONS = NO; 669 | ENABLE_STRICT_OBJC_MSGSEND = YES; 670 | GCC_C_LANGUAGE_STANDARD = gnu99; 671 | GCC_NO_COMMON_BLOCKS = YES; 672 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 673 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 674 | GCC_WARN_UNDECLARED_SELECTOR = YES; 675 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 676 | GCC_WARN_UNUSED_FUNCTION = YES; 677 | GCC_WARN_UNUSED_VARIABLE = YES; 678 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 679 | MTL_ENABLE_DEBUG_INFO = NO; 680 | SDKROOT = iphoneos; 681 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 682 | VALIDATE_PRODUCT = YES; 683 | }; 684 | name = Release; 685 | }; 686 | CC5A1A1C1CEADE59007238F3 /* Debug */ = { 687 | isa = XCBuildConfiguration; 688 | buildSettings = { 689 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 690 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 691 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 692 | INFOPLIST_FILE = JSONShootout/Info.plist; 693 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 694 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-bit.JSONShootout"; 695 | PRODUCT_NAME = "$(TARGET_NAME)"; 696 | SWIFT_VERSION = 3.0; 697 | }; 698 | name = Debug; 699 | }; 700 | CC5A1A1D1CEADE59007238F3 /* Release */ = { 701 | isa = XCBuildConfiguration; 702 | buildSettings = { 703 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 704 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 705 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 706 | INFOPLIST_FILE = JSONShootout/Info.plist; 707 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 708 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-bit.JSONShootout"; 709 | PRODUCT_NAME = "$(TARGET_NAME)"; 710 | SWIFT_VERSION = 3.0; 711 | }; 712 | name = Release; 713 | }; 714 | CC5A1A1F1CEADE59007238F3 /* Debug */ = { 715 | isa = XCBuildConfiguration; 716 | buildSettings = { 717 | INFOPLIST_FILE = JSONShootoutTests/Info.plist; 718 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 719 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-bit.JSONShootoutTests"; 720 | PRODUCT_NAME = "$(TARGET_NAME)"; 721 | SWIFT_VERSION = 3.0; 722 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JSONShootout.app/JSONShootout"; 723 | }; 724 | name = Debug; 725 | }; 726 | CC5A1A201CEADE59007238F3 /* Release */ = { 727 | isa = XCBuildConfiguration; 728 | buildSettings = { 729 | INFOPLIST_FILE = JSONShootoutTests/Info.plist; 730 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 731 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-bit.JSONShootoutTests"; 732 | PRODUCT_NAME = "$(TARGET_NAME)"; 733 | SWIFT_VERSION = 3.0; 734 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JSONShootout.app/JSONShootout"; 735 | }; 736 | name = Release; 737 | }; 738 | CC9786B51CEBABE7005A5DEA /* Debug */ = { 739 | isa = XCBuildConfiguration; 740 | buildSettings = { 741 | CLANG_ENABLE_MODULES = YES; 742 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 743 | CURRENT_PROJECT_VERSION = 1; 744 | DEFINES_MODULE = YES; 745 | DYLIB_COMPATIBILITY_VERSION = 1; 746 | DYLIB_CURRENT_VERSION = 1; 747 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 748 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 749 | INFOPLIST_FILE = ModelObjects/Info.plist; 750 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 751 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 752 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-bit.ModelObjects"; 753 | PRODUCT_NAME = "$(TARGET_NAME)"; 754 | SKIP_INSTALL = YES; 755 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 756 | SWIFT_VERSION = 3.0; 757 | TARGETED_DEVICE_FAMILY = "1,2"; 758 | VERSIONING_SYSTEM = "apple-generic"; 759 | VERSION_INFO_PREFIX = ""; 760 | }; 761 | name = Debug; 762 | }; 763 | CC9786B61CEBABE7005A5DEA /* Release */ = { 764 | isa = XCBuildConfiguration; 765 | buildSettings = { 766 | CLANG_ENABLE_MODULES = YES; 767 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 768 | CURRENT_PROJECT_VERSION = 1; 769 | DEFINES_MODULE = YES; 770 | DYLIB_COMPATIBILITY_VERSION = 1; 771 | DYLIB_CURRENT_VERSION = 1; 772 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 773 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 774 | INFOPLIST_FILE = ModelObjects/Info.plist; 775 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 776 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 777 | PRODUCT_BUNDLE_IDENTIFIER = "com.swift-bit.ModelObjects"; 778 | PRODUCT_NAME = "$(TARGET_NAME)"; 779 | SKIP_INSTALL = YES; 780 | SWIFT_VERSION = 3.0; 781 | TARGETED_DEVICE_FAMILY = "1,2"; 782 | VERSIONING_SYSTEM = "apple-generic"; 783 | VERSION_INFO_PREFIX = ""; 784 | }; 785 | name = Release; 786 | }; 787 | /* End XCBuildConfiguration section */ 788 | 789 | /* Begin XCConfigurationList section */ 790 | CC5A19F91CEADE59007238F3 /* Build configuration list for PBXProject "JSONShootout" */ = { 791 | isa = XCConfigurationList; 792 | buildConfigurations = ( 793 | CC5A1A191CEADE59007238F3 /* Debug */, 794 | CC5A1A1A1CEADE59007238F3 /* Release */, 795 | ); 796 | defaultConfigurationIsVisible = 0; 797 | defaultConfigurationName = Release; 798 | }; 799 | CC5A1A1B1CEADE59007238F3 /* Build configuration list for PBXNativeTarget "JSONShootout" */ = { 800 | isa = XCConfigurationList; 801 | buildConfigurations = ( 802 | CC5A1A1C1CEADE59007238F3 /* Debug */, 803 | CC5A1A1D1CEADE59007238F3 /* Release */, 804 | ); 805 | defaultConfigurationIsVisible = 0; 806 | defaultConfigurationName = Release; 807 | }; 808 | CC5A1A1E1CEADE59007238F3 /* Build configuration list for PBXNativeTarget "JSONShootoutTests" */ = { 809 | isa = XCConfigurationList; 810 | buildConfigurations = ( 811 | CC5A1A1F1CEADE59007238F3 /* Debug */, 812 | CC5A1A201CEADE59007238F3 /* Release */, 813 | ); 814 | defaultConfigurationIsVisible = 0; 815 | defaultConfigurationName = Release; 816 | }; 817 | CC9786B91CEBABE7005A5DEA /* Build configuration list for PBXNativeTarget "ModelObjects" */ = { 818 | isa = XCConfigurationList; 819 | buildConfigurations = ( 820 | CC9786B51CEBABE7005A5DEA /* Debug */, 821 | CC9786B61CEBABE7005A5DEA /* Release */, 822 | ); 823 | defaultConfigurationIsVisible = 0; 824 | defaultConfigurationName = Release; 825 | }; 826 | /* End XCConfigurationList section */ 827 | }; 828 | rootObject = CC5A19F61CEADE59007238F3 /* Project object */; 829 | } 830 | -------------------------------------------------------------------------------- /JSONShootout.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JSONShootout.xcodeproj/xcshareddata/xcschemes/JSONShootout.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 | 66 | 67 | 73 | 74 | 76 | 77 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /JSONShootout.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 21 | 22 | 24 | 25 | 27 | 28 | 30 | 31 | 33 | 34 | 36 | 37 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /JSONShootout/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/16/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // 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. 23 | // 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. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // 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. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // 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. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /JSONShootout/Assets.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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /JSONShootout/Base.lproj/LaunchScreen.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 | 27 | 28 | -------------------------------------------------------------------------------- /JSONShootout/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 | -------------------------------------------------------------------------------- /JSONShootout/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 | 40 | 41 | -------------------------------------------------------------------------------- /JSONShootout/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/16/16. 6 | // Copyright © 2016 Bart Whiteley. 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 | -------------------------------------------------------------------------------- /JSONShootoutTests/Decodable_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Marshal_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import Decodable 12 | 13 | class Decodable_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | let d:NSDictionary = try! JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSDictionary 18 | XCTAssert(d.count > 0) 19 | } 20 | } 21 | 22 | func testPerformance() { 23 | let dict = try! JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSDictionary 24 | 25 | self.measure { 26 | let programs:[Program] = try! dict => "ProgramList" => "Programs" 27 | XCTAssert(programs.count > 1000) 28 | } 29 | } 30 | 31 | 32 | private lazy var data:Data = { 33 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 34 | let data = try! Data(contentsOf: path!) 35 | return data 36 | }() 37 | 38 | } 39 | -------------------------------------------------------------------------------- /JSONShootoutTests/Freddy_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Freddy_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Kartik Patel on 11/24/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import Freddy 12 | 13 | class Freddy_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | let json = try! JSON(data:self.data as Data) 18 | XCTAssert(try! json.getDictionary().count > 0) 19 | } 20 | } 21 | 22 | func testPerformance() { 23 | let json = try! JSON(data:self.data as Data) 24 | 25 | self.measure { 26 | let programs = try! json.getArray(at: "ProgramList", "Programs").map(Program.init) 27 | XCTAssert(programs.count > 1000) 28 | } 29 | } 30 | 31 | private lazy var data:Data = { 32 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 33 | let data = try! Data(contentsOf: path!) 34 | return data 35 | }() 36 | 37 | } 38 | -------------------------------------------------------------------------------- /JSONShootoutTests/Genome_Test.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Genome_Test.swift 3 | // JSONShootout 4 | // 5 | // Created by Wane Wang on 10/28/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import Genome 12 | import GenomeFoundation 13 | 14 | class Genome_Test: XCTestCase { 15 | 16 | func testPerformance() { 17 | let json = try! self.data.makeNode() 18 | self.measure { 19 | guard let datas = json["ProgramList", "Programs"] else { 20 | XCTFail("do not get the correct data") 21 | return 22 | } 23 | let programs: [Program] = try! [Program](node: datas) 24 | XCTAssert(programs.count > 1000) 25 | 26 | } 27 | } 28 | 29 | private lazy var data:Data = { 30 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 31 | let data = try! Data(contentsOf: path!) 32 | return data 33 | }() 34 | 35 | } 36 | -------------------------------------------------------------------------------- /JSONShootoutTests/Gloss_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Gloss_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Ehsan Rezaie on 10/27/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import Gloss 12 | 13 | class Gloss_Tests: XCTestCase { 14 | 15 | func testPerformance() { 16 | 17 | let dict: [String: Any] = try! JSONSerialization.jsonObject(with: self.data, options: []) as! [String: Any] 18 | 19 | self.measure { 20 | let programs: [Program] = "ProgramList.Programs" <~~ dict ?? [] 21 | XCTAssert(programs.count > 1000) 22 | } 23 | } 24 | 25 | private lazy var data:Data = { 26 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 27 | let data = try! Data(contentsOf: path!) 28 | return data 29 | }() 30 | 31 | } 32 | -------------------------------------------------------------------------------- /JSONShootoutTests/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 | -------------------------------------------------------------------------------- /JSONShootoutTests/JSON_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftyJSON_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 6/1/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import JSON 12 | 13 | class JSON_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | do { 18 | 19 | let json = try JSON.Parser.parse(self.data) 20 | 21 | XCTAssert((json.object?.count ?? 0) > 0) 22 | } catch { 23 | XCTFail("Failed to parse: \(error)") 24 | } 25 | } 26 | } 27 | 28 | func testPerformance() { 29 | do { 30 | 31 | let json = try JSON.Parser.parse(self.data) 32 | 33 | self.measure { 34 | do { 35 | 36 | let programRA = json["ProgramList"]?["Programs"]?.array ?? [] 37 | let programs = try programRA.map(Program.init) 38 | XCTAssert(programs.count > 1000) 39 | } catch { 40 | XCTFail("Mapping did fail: \(error)") 41 | } 42 | } 43 | 44 | } catch { 45 | XCTFail("Failed to parse: \(error)") 46 | } 47 | } 48 | 49 | private lazy var data:Data = { 50 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 51 | let data = try! Data(contentsOf: path!) 52 | return data 53 | }() 54 | 55 | } 56 | -------------------------------------------------------------------------------- /JSONShootoutTests/Mapper_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Mapper_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import Mapper 12 | 13 | class Mapper_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | let d:NSDictionary = try! JSONSerialization.jsonObject(with:self.data, options: []) as! NSDictionary 18 | XCTAssert(d.count > 0) 19 | } 20 | } 21 | 22 | func testPerformance() { 23 | 24 | let dict = try! JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSDictionary 25 | let mapper = Mapper(JSON: dict) 26 | 27 | self.measure { 28 | let programs:[Program] = try! mapper.from("ProgramList.Programs") 29 | XCTAssert(programs.count > 1000) 30 | } 31 | } 32 | 33 | private lazy var data:Data = { 34 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json")! 35 | let data = try! Data(contentsOf: path) 36 | return data 37 | }() 38 | 39 | } 40 | -------------------------------------------------------------------------------- /JSONShootoutTests/Marshal_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Marshal_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import Marshal 12 | 13 | class Marshal_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | let d:NSDictionary = try! JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSDictionary 18 | XCTAssert(d.count > 0) 19 | } 20 | } 21 | 22 | func testTypedDeserialization() { 23 | self.measure { 24 | let json = try! JSONParser.JSONObjectWithData(self.data as Data) 25 | XCTAssert(json.count > 0) 26 | } 27 | } 28 | 29 | func testDictionaryPerformance() { 30 | let json = try! JSONParser.JSONObjectWithData(data as Data) 31 | 32 | self.measure { 33 | let programs:[Program] = try! json.value(for:"ProgramList.Programs") 34 | XCTAssert(programs.count > 1000) 35 | } 36 | } 37 | 38 | func testNSDictionaryPerformance() { 39 | let json = try! JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSDictionary 40 | 41 | self.measure { 42 | //for _ in 0..<10 { 43 | //while true { 44 | let programs:[Program] = try! json.value(for: "ProgramList.Programs") 45 | XCTAssert(programs.count > 1000) 46 | //} 47 | } 48 | } 49 | 50 | private lazy var data:Data = { 51 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 52 | let data = try! Data(contentsOf: path!) 53 | return data 54 | }() 55 | 56 | } 57 | -------------------------------------------------------------------------------- /JSONShootoutTests/ObjectMapper_Test.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectMapper_Test.swift 3 | // JSONShootout 4 | // 5 | // Created by Denis Bogomolov on 25/10/2016. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ObjectMapper 11 | import ModelObjects 12 | 13 | class ObjectMapper_Test: XCTestCase { 14 | struct ProgramList: ImmutableMappable { 15 | let programs: [Program] 16 | init(map: Map) throws { 17 | programs = try map.value("ProgramList.Programs") 18 | } 19 | func mapping(map: Map) { 20 | programs >>> map["ProgramList.Programs"] 21 | } 22 | } 23 | 24 | func testPerformance() { 25 | let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String : Any] 26 | self.measure { 27 | let list: ProgramList = try! ProgramList(JSON: json) 28 | XCTAssert(list.programs.count > 1000) 29 | } 30 | } 31 | 32 | private lazy var data:Data = { 33 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json")! 34 | let data = try! Data(contentsOf: path) 35 | return data 36 | }() 37 | } 38 | -------------------------------------------------------------------------------- /JSONShootoutTests/PMJSON_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PMJSON_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Kevin Ballard on 11/4/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import PMJSON 12 | 13 | class PMJSON_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | do { 18 | let json = try JSON.decode(self.data) 19 | 20 | XCTAssert(json.object?.count ?? 0 > 0) 21 | } catch { 22 | XCTFail("Failed to parse: \(error)") 23 | } 24 | } 25 | } 26 | 27 | func testPerformance() { 28 | do { 29 | let json = try JSON.decode(data) 30 | 31 | self.measure { 32 | do { 33 | let programs = try json.getObject("ProgramList", { try $0.mapArray("Programs", Program.init(pmjson:)) }) 34 | XCTAssert(programs.count > 1000) 35 | } catch { 36 | XCTFail("Mapping did fail: \(error)") 37 | } 38 | } 39 | } catch { 40 | XCTFail("Failed to parse: \(error)") 41 | } 42 | } 43 | 44 | private lazy var data: Data = { 45 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json")! 46 | let data = try! Data(contentsOf: path) 47 | return data 48 | }() 49 | } 50 | -------------------------------------------------------------------------------- /JSONShootoutTests/SwiftyJSON_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftyJSON_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 6/1/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ModelObjects 11 | import SwiftyJSON 12 | 13 | class SwiftyJSON_Tests: XCTestCase { 14 | 15 | func testDeserialization() { 16 | self.measure { 17 | let json = JSON(data:self.data as Data) 18 | XCTAssert(json.count > 0) 19 | } 20 | } 21 | 22 | func testPerformance() { 23 | let json = JSON(data:self.data as Data) 24 | self.measure { 25 | let programRA = json["ProgramList"]["Programs"].arrayValue 26 | let programs = programRA.map(Program.init) 27 | XCTAssert(programs.count > 1000) 28 | } 29 | } 30 | 31 | private lazy var data:Data = { 32 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 33 | let data = try! Data(contentsOf: path!) 34 | return data 35 | }() 36 | 37 | } 38 | -------------------------------------------------------------------------------- /JSONShootoutTests/Unbox_Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Unbox_Tests.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Unbox 11 | import ModelObjects 12 | 13 | class Unbox_Tests: XCTestCase { 14 | 15 | func testPerformance() { 16 | 17 | let dict = try! JSONSerialization.jsonObject(with: self.data, options: []) 18 | 19 | self.measure { 20 | let programs:[Program] = try! unbox(dictionary: dict as! UnboxableDictionary, atKeyPath: "ProgramList.Programs") 21 | XCTAssert(programs.count > 1000) 22 | } 23 | } 24 | 25 | private lazy var data:Data = { 26 | let path = Bundle(for: type(of: self)).url(forResource: "Large", withExtension: "json") 27 | let data = try! Data(contentsOf: path!) 28 | return data 29 | }() 30 | 31 | } 32 | -------------------------------------------------------------------------------- /ModelObjects/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 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ModelObjects/ModelObjects.h: -------------------------------------------------------------------------------- 1 | // 2 | // ModelObjects.h 3 | // ModelObjects 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ModelObjects. 12 | FOUNDATION_EXPORT double ModelObjectsVersionNumber; 13 | 14 | //! Project version string for ModelObjects. 15 | FOUNDATION_EXPORT const unsigned char ModelObjectsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /ModelObjects/NSDate+JSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+JSON.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Marshal 11 | import Mapper 12 | 13 | // Support for Marshal 14 | extension Date : ValueType { 15 | public static func value(_ object: Any) throws -> Date { 16 | guard let dateString = object as? String else { 17 | throw MarshalError.typeMismatch(expected: String.self, actual: type(of: object)) 18 | } 19 | guard let date = Date.fromISO8601String(dateString) else { 20 | throw MarshalError.typeMismatch(expected: "ISO8601 date string", actual: dateString) 21 | } 22 | return date 23 | } 24 | } 25 | 26 | extension Date { 27 | @nonobjc static let ISO8601SecondFormatter:DateFormatter = { 28 | let formatter = DateFormatter() 29 | formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"; 30 | let tz = TimeZone(abbreviation:"GMT") 31 | formatter.timeZone = tz 32 | return formatter 33 | }() 34 | 35 | static func fromISO8601String(_ dateString:String) -> Date? { 36 | if let date = ISO8601SecondFormatter.date(from: dateString) { 37 | return date 38 | } 39 | return .none 40 | } 41 | } 42 | 43 | 44 | // Support for Mapper 45 | extension Date: Convertible { 46 | public static func fromMap(_ value: Any) throws -> Date { 47 | guard let string = value as? String else { 48 | throw MapperError.convertibleError(value: value, type: String.self) 49 | } 50 | 51 | if let date = ISO8601SecondFormatter.date(from: string) { 52 | return date 53 | } 54 | 55 | throw MapperError.customError(field: nil, message: "'\(string)' is not a valid Date") 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ModelObjects/Program+Decodable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Decodable.swift 3 | // JSONShootout 4 | // 5 | // Created by Alessandro Orrù on 25/10/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Decodable 11 | 12 | extension Program: Decodable { 13 | public static func decode(_ json: Any) throws -> Program { 14 | return try Program( 15 | title: json => "Title", 16 | chanId: json => "Channel" => "ChanId", 17 | // startTime = json => "StartTime", 18 | // endTime = json => "EndTime", 19 | description: json => "Description", 20 | subtitle: json => "SubTitle", 21 | recording: json => "Recording", 22 | season: Int(json => "Season" as String), 23 | episode: Int(json => "Episode" as String) 24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ModelObjects/Program+Freddy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Freddy.swift 3 | // JSONShootout 4 | // 5 | // Created by Kartik Patel on 11/24/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import Freddy 10 | 11 | 12 | extension Program: JSONDecodable { 13 | public init(json: JSON) throws { 14 | title = try json.getString(at: "Title") 15 | chanId = try json.getString(at: "Channel", "ChanId") 16 | description = try json.getString(at: "Description") 17 | subtitle = try json.getString(at: "SubTitle") 18 | season = try json.getString(at: "Season").int 19 | episode = try json.getString(at: "Episode").int 20 | recording = try Recording(json: json["Recording"]!) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ModelObjects/Program+Genome.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Genome.swift 3 | // JSONShootout 4 | // 5 | // Created by Wane Wang on 10/27/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import Genome 10 | 11 | extension Program: MappableObject { 12 | 13 | public init(map: Map) throws { 14 | title = try map.extract("Title") { 15 | $0 ?? "" 16 | } 17 | chanId = try map.extract("channel", "ChanId") { 18 | $0 ?? "" 19 | } 20 | description = try map.extract("Description") 21 | subtitle = try map.extract("SubTitle") 22 | season = try map.extract("Season") 23 | episode = try map.extract("Episode") 24 | recording = try Recording(node: try map.extract("Recording")) 25 | } 26 | 27 | public func sequence(_ map: Map) throws { 28 | try title ~> map["Title"] 29 | try chanId ~> map["channel", "ChanId"] 30 | try description ~> map["Description"] 31 | try season ~> map["Season"] 32 | try episode ~> map["Episode"] 33 | try recording ~> map["Recording"] 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ModelObjects/Program+Gloss.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Gloss.swift 3 | // JSONShootout 4 | // 5 | 6 | import Gloss 7 | 8 | extension Program: Decodable { 9 | 10 | public init?(json: JSON) { 11 | 12 | title = "Title" <~~ json ?? "" 13 | chanId = "channel.ChanId" <~~ json ?? "" 14 | description = "Description" <~~ json 15 | subtitle = "SubTitle" <~~ json 16 | season = "Season" <~~ json 17 | episode = "Episode" <~~ json 18 | recording = ("Recording" <~~ json)! 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ModelObjects/Program+JSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+JSON.swift 3 | // JSONShootout 4 | // 5 | 6 | import JSON 7 | 8 | extension Program: JSONInitializable { 9 | 10 | public init(json:JSON) throws { 11 | 12 | title = try json.get("Title", default: "") 13 | chanId = try json["channel"]?.get("ChanId", default: "") ?? "" 14 | description = try json.get("Description") 15 | subtitle = try json.get("SubTitle") 16 | season = try json.get("Season") 17 | episode = try json.get("Episode") 18 | recording = try json.get("Recording") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ModelObjects/Program+Mapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Mapper.swift 3 | // JSONShootout 4 | // 5 | 6 | import Mapper 7 | -------------------------------------------------------------------------------- /ModelObjects/Program+Marshal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Marshal.swift 3 | // JSONShootout 4 | // 5 | 6 | import Marshal 7 | 8 | extension Program: Unmarshaling { 9 | public init(object json: MarshaledObject) throws { 10 | title = try json.value(for:"Title") 11 | chanId = try json.value(for:"Channel.ChanId") 12 | // startTime = try json.value(for:"StartTime") 13 | // endTime = try json.value(for:"EndTime") 14 | description = try json.value(for:"Description") 15 | subtitle = try json.value(for:"SubTitle") 16 | recording = try json.value(for:"Recording") 17 | season = (try json.value(for:"Season") as String?).flatMap({Int($0)}) 18 | episode = (try json.value(for:"Episode") as String?).flatMap({Int($0)}) 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /ModelObjects/Program+ObjectMapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+ObjectMapper.swift 3 | // JSONShootout 4 | // 5 | // Created by Denis Bogomolov on 25/10/2016. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import ObjectMapper 10 | 11 | extension Program: ImmutableMappable { 12 | public init(map: Map) throws { 13 | title = try map.value("Title") 14 | chanId = try map.value("Channel.ChanId") 15 | description = try? map.value("Description") 16 | subtitle = try? map.value("SubTitle") 17 | recording = try map.value("Recording") 18 | season = try? map.value("Season") 19 | episode = try? map.value("Episode") 20 | } 21 | public func mapping(map: Map) { 22 | title >>> map["Title"] 23 | chanId >>> map["Channel.ChanId"] 24 | description >>> map["Description"] 25 | subtitle >>> map["SubTitle"] 26 | recording >>> map["Recording"] 27 | season >>> map["Season"] 28 | episode >>> map["Episode"] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ModelObjects/Program+PMJSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+PMJSON.swift 3 | // JSONShootout 4 | // 5 | // Created by Kevin Ballard on 11/4/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import PMJSON 10 | 11 | extension Program { 12 | public init(pmjson json: JSON) throws { 13 | // Should the following 2 default to ""? Seems like they should just throw an error if not present. 14 | title = try json.getStringOrNil("Title") ?? "" 15 | chanId = try json.getObjectOrNil("channel", { try $0.getStringOrNil("ChanId") }) ?? "" 16 | description = try json.getStringOrNil("Description") 17 | subtitle = try json.getStringOrNil("SubTitle") 18 | season = try json.toIntOrNil("Season") 19 | episode = try json.toIntOrNil("Episode") 20 | recording = try json.getObject("Recording", { try Recording(pmjson: JSON($0)) }) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ModelObjects/Program+SwiftyJSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+SwiftyJSON.swift 3 | // JSONShootout 4 | // 5 | 6 | import SwiftyJSON 7 | 8 | extension Program { // SwiftyJSON 9 | public init(json:JSON) { 10 | title = json["Title"].stringValue 11 | chanId = json["Channel"]["ChanId"].stringValue 12 | description = json["Description"].string 13 | subtitle = json["SubTitle"].string 14 | season = json["Season"].int 15 | episode = json["Episode"].int 16 | recording = Recording(json: json["Recording"]) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ModelObjects/Program+Unbox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program+Unbox.swift 3 | // JSONShootout 4 | // 5 | 6 | import Unbox 7 | 8 | extension Program: Unboxable { 9 | public init(unboxer: Unboxer) throws { 10 | title = try unboxer.unbox(key:"Title") 11 | chanId = try unboxer.unbox(keyPath:"Channel.ChanId") 12 | // startTime = unboxer.unbox(key:"StartTime", formatter:NSDate.ISO8601SecondFormatter) 13 | // endTime = unboxer.unbox(key:"EndTime", formatter:NSDate.ISO8601SecondFormatter) 14 | description = unboxer.unbox(key:"Description") 15 | subtitle = unboxer.unbox(key:"SubTitle") 16 | recording = try unboxer.unbox(key:"Recording") 17 | season = unboxer.unbox(key:"Season") 18 | episode = unboxer.unbox(key:"Episode") 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /ModelObjects/Program.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Program.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | public struct Program { 10 | 11 | let title:String 12 | let chanId:String 13 | // Date parsing is slow. Remove dates to better measure performance. 14 | // let startTime:NSDate 15 | // let endTime:NSDate 16 | let description:String? 17 | let subtitle:String? 18 | let recording:Recording 19 | let season:Int? 20 | let episode:Int? 21 | } 22 | 23 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Decodable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Decodable.swift 3 | // JSONShootout 4 | // 5 | // Created by Alessandro Orrù on 25/10/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Decodable 11 | 12 | 13 | extension Recording : Decodable { 14 | public static func decode(_ json: Any) throws -> Recording { 15 | return try Recording( 16 | startTsStr: json => "StartTs", 17 | status: Status(rawValue: json => "Status") ?? .Unknown, 18 | recordId: json => "RecordId", 19 | recGroup: RecGroup(rawValue: json => "RecGroup") ?? .Unknown 20 | ) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Freddy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Freddy.swift 3 | // JSONShootout 4 | // 5 | // Created by Kartik Patel on 11/25/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import Freddy 10 | 11 | extension Recording { 12 | public init(json: JSON) throws { 13 | startTsStr = try json.getString(at: "StartTs") 14 | recordId = try json.getString(at: "RecordId") 15 | status = try Status(rawValue: json.getString(at: "Status")) ?? .Unknown 16 | recGroup = try RecGroup(rawValue: json.getString(at: "RecGroup")) ?? .Unknown 17 | } 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Genome.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Genome.swift 3 | // JSONShootout 4 | // 5 | // Created by Wane Wang on 10/27/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import Genome 10 | 11 | extension Recording: MappableObject { 12 | 13 | public init(map: Map) throws { 14 | startTsStr = try map.extract("StartTs") 15 | status = try map.extract("Status") { Status(rawValue: $0) ?? .Unknown } 16 | recordId = try map.extract("RecordId") 17 | recGroup = try map.extract("RecGroup") { RecGroup(rawValue: $0) ?? .Unknown } 18 | } 19 | 20 | public func sequence(_ map: Map) throws { 21 | // demo for transform object to dictionary 22 | try startTsStr ~> map["StartTs"] 23 | try status ~> map["Status"].transformToNode { $0.rawValue } 24 | try recordId ~> map["RecordId"] 25 | try recGroup ~> map["RecGroup"].transformToNode { $0.rawValue } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Gloss.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Gloss.swift 3 | // JSONShootout 4 | // 5 | 6 | import Gloss 7 | 8 | extension Recording: Decodable { 9 | 10 | public init?(json: JSON) { 11 | self.startTsStr = "StartTs" <~~ json ?? "" 12 | self.recordId = "RecordId" <~~ json ?? "" 13 | self.status = "Status" <~~ json ?? Status.Unknown 14 | self.recGroup = "RecGroup" <~~ json ?? RecGroup.Unknown 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ModelObjects/Recording+JSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+JSON.swift 3 | // JSONShootout 4 | // 5 | 6 | import JSON 7 | 8 | extension Recording: JSONInitializable { 9 | 10 | public init(json: JSON) throws { 11 | 12 | self.startTsStr = try json.get("StartTs") 13 | self.recordId = try json.get("RecordId") 14 | self.status = try json.get("Status", default: Status.Unknown) 15 | self.recGroup = try json.get("RecGroup", default: RecGroup.Unknown) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Mapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Mapper.swift 3 | // JSONShootout 4 | // 5 | 6 | import Mapper 7 | 8 | extension Recording: Mappable { 9 | public init(map: Mapper) throws { 10 | // startTs = map.optionalFrom("StartTs") 11 | // endTs = map.optionalFrom("EndTs") 12 | startTsStr = try map.from("StartTs") 13 | recordId = try map.from("RecordId") 14 | status = map.optionalFrom("Status") ?? .Unknown 15 | recGroup = map.optionalFrom("RecGroup") ?? .Unknown 16 | } 17 | } 18 | 19 | extension Program: Mappable { 20 | public init(map: Mapper) throws { 21 | title = try map.from("Title") 22 | chanId = try map.from("Channel.ChanId") 23 | // startTime = try map.from("StartTime") 24 | // endTime = try map.from("EndTime") 25 | description = try map.from("Description") 26 | subtitle = try map.from("SubTitle") 27 | recording = try map.from("Recording") 28 | season = (try map.from("Season") as String?).flatMap({Int($0)}) 29 | episode = (try map.from("Episode") as String?).flatMap({Int($0)}) 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Marshal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Marshal.swift 3 | // JSONShootout 4 | // 5 | 6 | import Marshal 7 | 8 | extension Recording: Unmarshaling { 9 | public init(object json:MarshaledObject) throws { 10 | // startTs = try? json.value(for:"StartTs") 11 | // endTs = try? json.value(for:"EndTs") 12 | startTsStr = try json.value(for:"StartTs") 13 | recordId = try json.value(for:"RecordId") 14 | status = (try? json.value(for:"Status")) ?? .Unknown 15 | recGroup = (try? json.value(for:"RecGroup")) ?? .Unknown 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /ModelObjects/Recording+ObjectMapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+ObjectMapper.swift 3 | // JSONShootout 4 | // 5 | // Created by Denis Bogomolov on 25/10/2016. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import ObjectMapper 10 | 11 | extension Recording: ImmutableMappable { 12 | public init(map: Map) throws { 13 | startTsStr = try map.value("StartTs") 14 | status = (try? map.value("Status")) ?? .Unknown 15 | recordId = try map.value("RecordId") 16 | recGroup = (try? map.value("RecGroup")) ?? .Unknown 17 | } 18 | public func mapping(map: Map) { 19 | startTsStr >>> map["StartTs"] 20 | status >>> map["Status"] 21 | recordId >>> map["RecordId"] 22 | recGroup >>> map["RecGroup"] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ModelObjects/Recording+PMJSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+PMJSON.swift 3 | // JSONShootout 4 | // 5 | // Created by Kevin Ballard on 11/4/16. 6 | // Copyright © 2016 SwiftBit. All rights reserved. 7 | // 8 | 9 | import PMJSON 10 | 11 | extension Recording { 12 | public init(pmjson json: JSON) throws { 13 | startTsStr = try json.getString("StartTs") 14 | recordId = try json.getString("RecordId") 15 | status = try json.getStringOrNil("Status").flatMap({ Status(rawValue: $0) }) ?? .Unknown 16 | recGroup = try json.getStringOrNil("RecGroup").flatMap({ RecGroup(rawValue: $0) }) ?? .Unknown 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ModelObjects/Recording+SwiftyJSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+SwiftyJSON.swift 3 | // JSONShootout 4 | // 5 | 6 | import SwiftyJSON 7 | 8 | extension Recording { // SwiftyJSON 9 | init(json:JSON) { 10 | startTsStr = json["StartTs"].stringValue 11 | recordId = json["RecordId"].stringValue 12 | if let raw = json["Status"].string { 13 | status = Status(rawValue: raw) ?? .Unknown 14 | } 15 | else { 16 | status = .Unknown 17 | } 18 | if let raw = json["RecGroup"].string { 19 | recGroup = RecGroup(rawValue: raw) ?? .Unknown 20 | } 21 | else { 22 | recGroup = .Unknown 23 | } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /ModelObjects/Recording+Unbox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording+Unbox.swift 3 | // JSONShootout 4 | // 5 | 6 | import Unbox 7 | 8 | extension Recording: Unboxable { 9 | public init(unboxer: Unboxer) throws { 10 | // startTs = unboxer.unbox(key:"StartTs", formatter:NSDate.ISO8601SecondFormatter) 11 | // endTs = unboxer.unbox(key:"EndTs", formatter:NSDate.ISO8601SecondFormatter) 12 | startTsStr = try unboxer.unbox(key:"StartTs") 13 | recordId = try unboxer.unbox(key:"RecordId") 14 | status = unboxer.unbox(key: "Status") ?? .Unknown 15 | recGroup = (unboxer.unbox(key: "RecGroup")) ?? .Unknown 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /ModelObjects/Recording.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Recording.swift 3 | // JSONShootout 4 | // 5 | // Created by Bart Whiteley on 5/17/16. 6 | // Copyright © 2016 Bart Whiteley. All rights reserved. 7 | // 8 | 9 | import Unbox 10 | 11 | public struct Recording { 12 | enum Status: String, UnboxableEnum { 13 | case None = "0" 14 | case Recorded = "-3" 15 | case Recording = "-2" 16 | case Unknown 17 | } 18 | 19 | enum RecGroup: String, UnboxableEnum { 20 | case Deleted = "Deleted" 21 | case Default = "Default" 22 | case LiveTV = "LiveTV" 23 | case Unknown 24 | } 25 | 26 | 27 | // Date parsing is slow. Remove dates to better measure performance. 28 | // let startTs:NSDate? 29 | // let endTs:NSDate? 30 | let startTsStr:String 31 | let status:Status 32 | let recordId:String 33 | let recGroup:RecGroup 34 | } 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # * Note about JSONDecoder in Swift 4 * 2 | To experiment with `JSONDecoder` in Swift 4, use the `swift4` branch. Some of the other implementations were removed from the `swift4` branch to get it to compile and run. Check the performance graph near end of this file to see the performance of `JSONDecoder` 3 | 4 | # Swift + JSON 5 | Since the first days of Swift, developers have been exploring strategies for dealing with JSON. While some call this "JSON Parsing", with [few](https://github.com/bignerdranch/Freddy) [exceptions](https://github.com/vdka/JSON) most people rely on `NSJSONSerialization` for the actual parsing. Most of the effort has gone into finding the best way to map JSON objects (dictionaries and arrays) into model objects (structs, classes, enums). 6 | 7 | ## A Convergence of Ideas 8 | 9 | 10 | Many projects have emerged to take on this challenge, employing various approaches and philosophies. It's interesting that several of these projects have taken a very similar approach, ostensibly independent of each other. Here are some examples: 11 | 12 | * [Marshal](https://github.com/utahiosmac/Marshal) 13 | * [Mapper](https://github.com/lyft/mapper) 14 | * [Unbox](https://github.com/JohnSundell/Unbox) 15 | * [Decodable](https://github.com/Anviking/Decodable) 16 | * [ObjectMapper](https://github.com/Hearst-DD/ObjectMapper) 17 | * [Gloss](https://github.com/hkellaway/Gloss) 18 | * [Genome](https://github.com/LoganWright/Genome) 19 | 20 | The power of the approach taken by these projects lies in the ability to easily map not only primitive JSON types, but also custom types and objects in a type safe manner. 21 | 22 | For example, the goal is to be able to do something like this: 23 | 24 | ```swift 25 | let title:String = try json.value(for: "header.title") 26 | let users:[User] = try json.value(for: "users") 27 | ``` 28 | 29 | All of the frameworks listed above leverage Swift's powerful type system to handle all of the details. 30 | 31 | ## A Detailed Look 32 | 33 | I put together a small project to compare these Swift JSON mappers. Let's look at some objects from a Digital Video Recorder feed: 34 | ### The Objects 35 | 36 | ```swift 37 | struct Recording { 38 | let startTs:NSDate? 39 | let endTs:NSDate? 40 | let startTsStr:String 41 | let status:Status // enum 42 | let recordId:String 43 | let recGroup:RecGroup // enum 44 | } 45 | 46 | struct Program { 47 | let title:String 48 | let chanId:String 49 | let startTime:NSDate 50 | let endTime:NSDate 51 | let description:String? 52 | let subtitle:String? 53 | let recording:Recording // nested object 54 | let season:Int? 55 | let episode:Int? 56 | } 57 | ``` 58 | 59 | Now let's look at how these objects would be extracted with each of the JSON mappers. We'll ignore proper error handling for this exercise. 60 | ### Marshal 61 | ```swift 62 | extension Recording: Unmarshaling { 63 | public init(object json:MarshaledObject) throws { 64 | startTs = try? json.value(for: "StartTs") 65 | endTs = try? json.value(for: "EndTs") 66 | startTsStr = try json.value(for: "StartTs") 67 | recordId = try json.value(for: "RecordId") 68 | status = (try? json.value(for: "Status")) ?? .Unknown 69 | recGroup = (try? json.value(for: "RecGroup")) ?? .Unknown 70 | } 71 | } 72 | 73 | extension Program: Unmarshaling { 74 | public init(object json: MarshaledObject) throws { 75 | title = try json.value(for: "Title") 76 | chanId = try json.value(for: "Channel.ChanId") 77 | startTime = try json.value(for: "StartTime") 78 | endTime = try json.value(for: "EndTime") 79 | description = try json.value(for: "Description") 80 | subtitle = try json.value(for: "SubTitle") 81 | recording = try json.value(for: "Recording") 82 | season = (try json.value(for: "Season") as String?).flatMap({Int($0)}) 83 | episode = (try json.value(for: "Episode") as String?).flatMap({Int($0)}) 84 | } 85 | } 86 | 87 | // Extract an array of Programs 88 | let json = try! NSJSONSerialization.JSONObjectWithData(data, options: []) as! NSDictionary 89 | let programs:[Program] = try json.valueForKey("ProgramList.Programs") 90 | ``` 91 | 92 | ### Mapper 93 | 94 | ```swift 95 | extension Recording: Mappable { 96 | public init(map: Mapper) throws { 97 | startTs = map.optionalFrom("StartTs") 98 | endTs = map.optionalFrom("EndTs") 99 | startTsStr = try map.from("StartTs") 100 | recordId = try map.from("RecordId") 101 | status = map.optionalFrom("Status") ?? .Unknown 102 | recGroup = map.optionalFrom("RecGroup") ?? .Unknown 103 | } 104 | } 105 | 106 | extension Program: Mappable { 107 | public init(map: Mapper) throws { 108 | title = try map.from("Title") 109 | chanId = try map.from("Channel.ChanId") 110 | startTime = try map.from("StartTime") 111 | endTime = try map.from("EndTime") 112 | description = try map.from("Description") 113 | subtitle = try map.from("SubTitle") 114 | recording = try map.from("Recording") 115 | season = (try map.from("Season") as String?).flatMap({Int($0)}) 116 | episode = (try map.from("Episode") as String?).flatMap({Int($0)}) 117 | } 118 | } 119 | 120 | // Extract an array of Programs 121 | let dict = try! NSJSONSerialization.JSONObjectWithData(data, options: []) as! NSDictionary 122 | let mapper = Mapper(JSON: dict) 123 | let programs:[Program] = try! mapper.from("ProgramList.Programs") 124 | ``` 125 | 126 | ### Unbox 127 | 128 | ```swift 129 | extension Recording: Unboxable { 130 | public init(unboxer: Unboxer) throws { 131 | startTs = unboxer.unbox(key: "StartTs", formatter:NSDate.ISO8601SecondFormatter) 132 | endTs = unboxer.unbox(key: "EndTs", formatter:NSDate.ISO8601SecondFormatter) 133 | startTsStr = try unboxer.unbox(key: "StartTs") 134 | recordId = try unboxer.unbox(key: "RecordId") 135 | status = unboxer.unbox(key: "Status") ?? .Unknown 136 | recGroup = unboxer.unbox(key: "RecGroup") ?? .Unknown 137 | } 138 | } 139 | 140 | extension Program: Unboxable { 141 | public init(unboxer: Unboxer) throws { 142 | title = try unboxer.unbox(key: "Title") 143 | chanId = try unboxer.unbox(keyPath: "Channel.ChanId") 144 | startTime = try unboxer.unbox(key: "StartTime", formatter:NSDate.ISO8601SecondFormatter) 145 | endTime = try unboxer.unbox(key: "EndTime", formatter:NSDate.ISO8601SecondFormatter) 146 | description = unboxer.unbox(key: "Description") 147 | subtitle = unboxer.unbox(key: "SubTitle") 148 | recording = try unboxer.unbox(key: "Recording") 149 | season = unboxer.unbox(key: "Season") 150 | episode = unboxer.unbox(key: "Episode") 151 | } 152 | } 153 | 154 | // Extract an array of Programs 155 | let dict = try! NSJSONSerialization.JSONObjectWithData(data, options: []) as! UnboxableDictionary 156 | let programs:[Program] = try! unbox(dictionary: dict, atKeyPath: "ProgramList.Programs") 157 | ``` 158 | 159 | ### Decodable 160 | 161 | ```swift 162 | extension Recording : Decodable { 163 | public static func decode(_ json: Any) throws -> Recording { 164 | return try Recording( 165 | startTsStr: json => "StartTs", 166 | status: Status(rawValue: json => "Status") ?? .Unknown, 167 | recordId: json => "RecordId", 168 | recGroup: RecGroup(rawValue: json => "RecGroup") ?? .Unknown 169 | ) 170 | } 171 | } 172 | 173 | extension Program: Decodable { 174 | public static func decode(_ json: Any) throws -> Program { 175 | return try Program( 176 | title: json => "Title", 177 | chanId: json => "Channel" => "ChanId", 178 | startTime = json => "StartTime", 179 | endTime = json => "EndTime", 180 | description: json => "Description", 181 | subtitle: json => "SubTitle", 182 | recording: json => "Recording", 183 | season: Int(json => "Season" as String), 184 | episode: Int(json => "Episode" as String) 185 | ) 186 | } 187 | } 188 | 189 | // Extract an array of Programs 190 | let dict = try! NSJSONSerialization.JSONObjectWithData(data, options: []) as! NSDictionary 191 | let programs:[Program] = try! dict => "ProgramList" => "Programs" 192 | ``` 193 | 194 | ### Gloss 195 | ```swift 196 | extension Recording: Decodable { 197 | public init?(json: JSON) { 198 | self.startTsStr = "StartTs" <~~ json ?? "" 199 | self.recordId = "RecordId" <~~ json ?? "" 200 | self.status = "Status" <~~ json ?? Status.Unknown 201 | self.recGroup = "RecGroup" <~~ json ?? RecGroup.Unknown 202 | } 203 | } 204 | 205 | extension Program: Decodable { 206 | public init?(json: JSON) { 207 | title = "Title" <~~ json ?? "" 208 | chanId = "channel.ChanId" <~~ json ?? "" 209 | description = "Description" <~~ json 210 | subtitle = "SubTitle" <~~ json 211 | season = "Season" <~~ json 212 | episode = "Episode" <~~ json 213 | recording = ("Recording" <~~ json)! 214 | } 215 | } 216 | 217 | // Extract an array of Programs 218 | let dict: [String: Any] = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] 219 | let programs: [Program] = "ProgramList.Programs" <~~ dict ?? [] 220 | ``` 221 | 222 | ### Genome 223 | 224 | ```swift 225 | extension Recording: MappableObject { 226 | public init(map: Map) throws { 227 | startTsStr = try map.extract("StartTs") 228 | status = try map.extract("Status") { Status(rawValue: $0) ?? .Unknown } 229 | recordId = try map.extract("RecordId") 230 | recGroup = try map.extract("RecGroup") { RecGroup(rawValue: $0) ?? .Unknown } 231 | } 232 | public func sequence(_ map: Map) throws { } 233 | } 234 | 235 | extension Program: MappableObject { 236 | public init(map: Map) throws { 237 | title = try map.extract("Title") { $0 ?? "" } 238 | chanId = try map.extract("channel", "ChanId") { $0 ?? "" } 239 | description = try map.extract("Description") 240 | subtitle = try map.extract("SubTitle") 241 | season = try map.extract("Season") 242 | episode = try map.extract("Episode") 243 | recording = try Recording(node: try map.extract("Recording")) 244 | } 245 | public func sequence(_ map: Map) throws { } 246 | } 247 | 248 | // Extract an array of Programs 249 | let json = try! data.makeNode() 250 | let programs: [Program] = try! [Program](node: json["ProgramList", "Programs"]!) 251 | ``` 252 | 253 | ## Analysis 254 | You can immediately see the similarities between the three projects. I won't get into the details of how they work here. You can read more about each project, or read Jason Larsen's 255 | [three](http://jasonlarsen.me/2015/06/23/no-magic-json.html) 256 | [blog](http://jasonlarsen.me/2015/06/23/no-magic-json-pt2.html) 257 | [posts](http://jasonlarsen.me/2015/10/16/no-magic-json-pt3.html). 258 | 259 | Most of these JSON mappers can handle `NSURL`s. They can also handle `NSDate`s with the help of formatters. Marshal and Mapper automatically handle enums with raw types. Unbox requires enums to conform to a special protocol. The power of these projects lies in the ability to make the JSON mapper aware of new types, whether they be simple fields that can be transformed from a string such as dates, or more complex types and even nested types like our Program and Recording above. 260 | ## Type Safety 261 | 262 | Many of these projects provide a measure of type safety at compile time. The compiler is aware of what types are supported, so you can't attempt to extract a type that the JSON extractor can't handle. For example, the compiler won't let you try this: 263 | 264 | `let name: UIView = try json.value(for: "firstName")` 265 | 266 | This code will fail to compile because `UIView` does not conform to the necessary protocol. All of the projects in the Shootout support this compile-time safety except for ObjectMapper and Gloss. 267 | ## Protocol Extensions vs. Wrappers 268 | 269 | Many of these frameworks work by wrapping a dictionary in another object. Marshal differs in that it is implemented as a protocol with a protocol extension. Both `NSDictionary` and `Dictionary` conform to the protocol. Other types can easily conform to the protocol simply by providing an implementation for `optionalAny(for key: KeyType)`. 270 | ## What about SwiftyJSON? 271 | 272 | SwiftyJSON was one of the earliest projects to help Swift developers deal with JSON. Compared to more recent projects, SwiftyJSON is verbose and error prone. It doesn't take advantage of Swift's type system to enable safety, error handling, and expressive code. As you'll see below, the performance is quite bad as well. 273 | ## What about Argo? 274 | 275 | Argo requires two additional dependencies (Curry and Runes) which feels kind of heavy. The liberal use of custom operators is off-putting to many developers. When trying to map to the two model objects above with Argo, the Swift compiler emitted the dreaded error `Expression was too complex to be solved in reasonable time`. As a result Argo is more rigid and the model objects had to be changed to get things to work. Argo was the worst-performing framework tested. Because the model objects had to be changed to get Argo to work, the master branch does not have support for Argo. A separate `argo` branch is available if someone would like to see how it works. 276 | ## Performance 277 | Now that we have all of the JSON mappers processing the same JSON file, we can compare the performance of each. While measuring performance I noticed that a lot of time was spent in date parsing. Since this was common across all implementations, I removed the dates from the model objects to get a better comparison of the performance of the JSON mappers themselves. 278 | 279 | This graph shows time spent in each of the mappers as well as time spent in `NSJSONSerialization` for a reference. 280 | 281 | 282 | ![Performance Graph](https://raw.githubusercontent.com/bwhiteley/JSONShootout/master/images/performance.png) 283 | 284 | ### * A Note About vdka/json and Freddy 285 | You might notice that the "JSON" and "Freddy" bars in the graph are different from the rest. These projects use their own JSON deserializers instead of `NSJSONSerialization`. 286 | 287 | ## That Thing on the Swift Blog 288 | There was a Swift blog post about [working with JSON in Swift](https://developer.apple.com/swift/blog/?id=37). The concluding section seems to discourage the use of a JSON framework and instead use the features available in the Swift language itself. However, the post is referring specifically to abstractions that use reflection to automatically map between dictionaries and model objects. None of the frameworks evaluated here do that, but instead favor explicitness. The error handling example from the Swift blog post demonstrates why using a `guard let` approach to JSON is a bad idea for any significant amount of JSON processing. It is very verbose, repetitive, and error prone. The frameworks evaluated here provide a concise and declarative way to work with JSON while avoiding "magic." 289 | 290 | ## Conclusion 291 | If you are looking for a Swift JSON mapper, you might want to clone JSONShootout and compare these frameworks side-by-side yourself. 292 | ### Installation 293 | 1. Clone the project 294 | 2. Run `carthage bootstrap --no-build` 295 | 3. Open the workspace 296 | 4. Run the unit tests in the JSONShootoutTests target 297 | 298 | ## Contributing 299 | If you would like to add another framework for comparison, submit a pull request after making the following changes: 300 | 301 | 1. Add the new framework to the `Cartfile`. 302 | 2. Run `carthage update --no-build`. 303 | 3. Drag the new framework project to the top level of the workspace. 304 | 4. Add the new framework to the Linked Frameworks and Libraries section of the ModelObjects target. 305 | 5. Add the new framework to the Linked Frameworks and Libraries section of the JSONShootout target. 306 | 6. Add the new framework to the Embedded Binaries section of the JSONShootout target. 307 | 7. Make sure there are no duplicates in Linked Frameworks and Libraries (Xcode bug). 308 | 8. Check the project file (`JSONShootout.xcodeproj/project.pbxproj`). There should be no references to `Carthage` or user-specific derived data paths. See [this bug](http://www.openradar.me/radar?id=6091575503355904) for details. 309 | 9. Add new extensions to `Program` and `Recording`. See the existing files for an example. 310 | 10. Add a new unit test file. See existing files for an example. 311 | 312 | Full Disclosure: I contribute to the Marshal project. 313 | -------------------------------------------------------------------------------- /images/performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwhiteley/JSONShootout/0b2f7877efb3e8d644eec82e9cc5bff13862b87d/images/performance.png --------------------------------------------------------------------------------