diff --git a/.gitignore b/.gitignore index a2da796..09f7c94 100644 --- a/.gitignore +++ b/.gitignore @@ -162,3 +162,4 @@ xcuserdata # UNKNOWN: recommended by others, but I can't discover what these files are # # ...none. Everything is now explained. +Pods diff --git a/Podfile b/Podfile new file mode 100644 index 0000000..b3a9a2f --- /dev/null +++ b/Podfile @@ -0,0 +1,19 @@ +# Uncomment this line to define a global platform for your project +platform :osx, '10.10' + +target 'SwiftJson' do +pod 'ObjectMapper', '~> 0.11' +pod "SwiftyJSON", ">= 2.2" +pod 'Dollar' +pod 'Cent' +end + +target 'SwiftJsonTests' do +pod 'ObjectMapper', '~> 0.11' +pod "SwiftyJSON", ">= 2.2" +pod 'Dollar' +pod 'Cent' +end + +use_frameworks! + diff --git a/README.md b/README.md index e3c48ed..72897b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ ##Swift JSON## Swift JSON takes away the monotony of hand writing serialization code for JSON structures. + ###Caveats### -* Swift JSON generates code that requires a forked version of [SwiftyJSON](https://github.com/pvwoods/SwiftyJSON) to be included in your project. + +This project uses cocoa pod must be installed and run pods install on root project diff --git a/SwiftJson.xcodeproj/project.pbxproj b/SwiftJson.xcodeproj/project.pbxproj index 2b86f89..8190b87 100644 --- a/SwiftJson.xcodeproj/project.pbxproj +++ b/SwiftJson.xcodeproj/project.pbxproj @@ -7,17 +7,24 @@ objects = { /* Begin PBXBuildFile section */ - 073B4B53196B7D5000A62AF4 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073B4B52196B7D5000A62AF4 /* SwiftyJSON.swift */; }; - 073B4B54196B7D5000A62AF4 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073B4B52196B7D5000A62AF4 /* SwiftyJSON.swift */; }; 07859D7F194909F100D04588 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859D7E194909F100D04588 /* main.swift */; }; 07859D81194909F100D04588 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859D80194909F100D04588 /* ViewController.swift */; }; 07859D83194909F100D04588 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859D82194909F100D04588 /* AppDelegate.swift */; }; 07859D85194909F100D04588 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 07859D84194909F100D04588 /* Images.xcassets */; }; - 07859D94194909F100D04588 /* SwiftJsonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859D93194909F100D04588 /* SwiftJsonTests.swift */; }; - 07859D9E19490A9A00D04588 /* ModelGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859D9D19490A9A00D04588 /* ModelGenerator.swift */; }; - 07859DA019490AAE00D04588 /* IndentableOutput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859D9F19490AAE00D04588 /* IndentableOutput.swift */; }; 07859DA219491CD500D04588 /* MenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07859DA119491CD500D04588 /* MenuController.swift */; }; + 0BA6F9825CB93BB7617EB107 /* Pods_SwiftJson.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D223D5C29A10EFCEBDDBAA8 /* Pods_SwiftJson.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 3E79DB0B41638523B3303177 /* Pods_SwiftJsonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BFFDC2DFACDEB9163980C9F /* Pods_SwiftJsonTests.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 7E8A8D48194CB1790089D85D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7E8A8D46194CB1790089D85D /* MainMenu.xib */; }; + B27E45941AFEB97100D7EC8D /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B27E45931AFEB97100D7EC8D /* Generator.swift */; }; + B27E45951AFED26D00D7EC8D /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B27E45931AFEB97100D7EC8D /* Generator.swift */; }; + B2A978201AF6B02300B2BC8C /* NSScanner+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2A9781F1AF6B02300B2BC8C /* NSScanner+Swift.swift */; }; + B2D403161AF822970088E073 /* GeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403151AF822970088E073 /* GeneratorTests.swift */; }; + B2D403181AF8CC5D0088E073 /* ClassModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403171AF8CC5D0088E073 /* ClassModel.swift */; }; + B2D403191AF904CE0088E073 /* ClassModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403171AF8CC5D0088E073 /* ClassModel.swift */; }; + B2D403211AF921A30088E073 /* ClassModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403201AF921A30088E073 /* ClassModelTests.swift */; }; + B2D403231AF922340088E073 /* JSONUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403221AF922340088E073 /* JSONUtils.swift */; }; + B2D403251AF922DF0088E073 /* JSONUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403241AF922DF0088E073 /* JSONUtilsTests.swift */; }; + B2D403261AF9233C0088E073 /* JSONUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D403221AF922340088E073 /* JSONUtils.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -31,7 +38,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 073B4B52196B7D5000A62AF4 /* SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyJSON.swift; sourceTree = ""; }; 07859D79194909F000D04588 /* SwiftJson.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftJson.app; sourceTree = BUILT_PRODUCTS_DIR; }; 07859D7D194909F100D04588 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 07859D7E194909F100D04588 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; @@ -40,11 +46,23 @@ 07859D84194909F100D04588 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 07859D8D194909F100D04588 /* SwiftJsonTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftJsonTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 07859D92194909F100D04588 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 07859D93194909F100D04588 /* SwiftJsonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftJsonTests.swift; sourceTree = ""; }; - 07859D9D19490A9A00D04588 /* ModelGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModelGenerator.swift; sourceTree = ""; }; - 07859D9F19490AAE00D04588 /* IndentableOutput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndentableOutput.swift; sourceTree = ""; }; 07859DA119491CD500D04588 /* MenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = ""; }; + 0AF4D90A355893C0CEE0EE37 /* Pods-SwiftJsonTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftJsonTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftJsonTests/Pods-SwiftJsonTests.release.xcconfig"; sourceTree = ""; }; + 35A74A846D9D4D51C11FB2D4 /* Pods-SwiftJson.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftJson.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftJson/Pods-SwiftJson.debug.xcconfig"; sourceTree = ""; }; + 4D223D5C29A10EFCEBDDBAA8 /* Pods_SwiftJson.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftJson.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6BFFDC2DFACDEB9163980C9F /* Pods_SwiftJsonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftJsonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7E8A8D47194CB1790089D85D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 80BD305520F4EFFE3B982A84 /* Pods-SwiftJsonTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftJsonTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftJsonTests/Pods-SwiftJsonTests.debug.xcconfig"; sourceTree = ""; }; + B27DC36F1AF77685004C652E /* Dollar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Dollar.framework; path = "Pods/../build/Debug-iphoneos/Pods-SwiftJsonTests/Dollar.framework"; sourceTree = ""; }; + B27DC3711AF7768F004C652E /* Cent.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cent.framework; path = "Pods/../build/Debug-iphoneos/Pods-SwiftJson/Cent.framework"; sourceTree = ""; }; + B27E45931AFEB97100D7EC8D /* Generator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Generator.swift; sourceTree = ""; }; + B2A9781F1AF6B02300B2BC8C /* NSScanner+Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSScanner+Swift.swift"; sourceTree = ""; }; + B2D403151AF822970088E073 /* GeneratorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratorTests.swift; sourceTree = ""; }; + B2D403171AF8CC5D0088E073 /* ClassModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClassModel.swift; sourceTree = ""; }; + B2D403201AF921A30088E073 /* ClassModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClassModelTests.swift; sourceTree = ""; }; + B2D403221AF922340088E073 /* JSONUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONUtils.swift; sourceTree = ""; }; + B2D403241AF922DF0088E073 /* JSONUtilsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONUtilsTests.swift; sourceTree = ""; }; + C1733AEA159B850EADA5D67D /* Pods-SwiftJson.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftJson.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftJson/Pods-SwiftJson.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -52,6 +70,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0BA6F9825CB93BB7617EB107 /* Pods_SwiftJson.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -59,6 +78,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 3E79DB0B41638523B3303177 /* Pods_SwiftJsonTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -71,6 +91,8 @@ 07859D7B194909F000D04588 /* SwiftJson */, 07859D90194909F100D04588 /* SwiftJsonTests */, 07859D7A194909F000D04588 /* Products */, + 53C4CF8E471AF9EC751ED6AD /* Pods */, + CB9DBC876D8F76BDD4BB6103 /* Frameworks */, ); sourceTree = ""; }; @@ -86,14 +108,13 @@ 07859D7B194909F000D04588 /* SwiftJson */ = { isa = PBXGroup; children = ( - 073B4B52196B7D5000A62AF4 /* SwiftyJSON.swift */, + B2D4031A1AF91F7D0088E073 /* generator */, + 07859DA119491CD500D04588 /* MenuController.swift */, + B2A9781F1AF6B02300B2BC8C /* NSScanner+Swift.swift */, 07859D80194909F100D04588 /* ViewController.swift */, 07859D82194909F100D04588 /* AppDelegate.swift */, 07859D84194909F100D04588 /* Images.xcassets */, 7E8A8D46194CB1790089D85D /* MainMenu.xib */, - 07859D9D19490A9A00D04588 /* ModelGenerator.swift */, - 07859D9F19490AAE00D04588 /* IndentableOutput.swift */, - 07859DA119491CD500D04588 /* MenuController.swift */, 07859D7C194909F000D04588 /* Supporting Files */, ); path = SwiftJson; @@ -111,7 +132,9 @@ 07859D90194909F100D04588 /* SwiftJsonTests */ = { isa = PBXGroup; children = ( - 07859D93194909F100D04588 /* SwiftJsonTests.swift */, + B2D403241AF922DF0088E073 /* JSONUtilsTests.swift */, + B2D403201AF921A30088E073 /* ClassModelTests.swift */, + B2D403151AF822970088E073 /* GeneratorTests.swift */, 07859D91194909F100D04588 /* Supporting Files */, ); path = SwiftJsonTests; @@ -125,6 +148,38 @@ name = "Supporting Files"; sourceTree = ""; }; + 53C4CF8E471AF9EC751ED6AD /* Pods */ = { + isa = PBXGroup; + children = ( + 35A74A846D9D4D51C11FB2D4 /* Pods-SwiftJson.debug.xcconfig */, + C1733AEA159B850EADA5D67D /* Pods-SwiftJson.release.xcconfig */, + 80BD305520F4EFFE3B982A84 /* Pods-SwiftJsonTests.debug.xcconfig */, + 0AF4D90A355893C0CEE0EE37 /* Pods-SwiftJsonTests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + B2D4031A1AF91F7D0088E073 /* generator */ = { + isa = PBXGroup; + children = ( + B2D403171AF8CC5D0088E073 /* ClassModel.swift */, + B2D403221AF922340088E073 /* JSONUtils.swift */, + B27E45931AFEB97100D7EC8D /* Generator.swift */, + ); + name = generator; + sourceTree = ""; + }; + CB9DBC876D8F76BDD4BB6103 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B27DC3711AF7768F004C652E /* Cent.framework */, + B27DC36F1AF77685004C652E /* Dollar.framework */, + 4D223D5C29A10EFCEBDDBAA8 /* Pods_SwiftJson.framework */, + 6BFFDC2DFACDEB9163980C9F /* Pods_SwiftJsonTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -132,9 +187,12 @@ isa = PBXNativeTarget; buildConfigurationList = 07859D97194909F100D04588 /* Build configuration list for PBXNativeTarget "SwiftJson" */; buildPhases = ( + 453E0CC42F5EABAB3D4938E7 /* Check Pods Manifest.lock */, 07859D75194909F000D04588 /* Sources */, 07859D76194909F000D04588 /* Frameworks */, 07859D77194909F000D04588 /* Resources */, + DC6D376FAB568EF83785D6BF /* Embed Pods Frameworks */, + A0FA70CE020EE0F646699F1B /* Copy Pods Resources */, ); buildRules = ( ); @@ -149,9 +207,12 @@ isa = PBXNativeTarget; buildConfigurationList = 07859D9A194909F100D04588 /* Build configuration list for PBXNativeTarget "SwiftJsonTests" */; buildPhases = ( + 5A84E93669C8A8F442893764 /* Check Pods Manifest.lock */, 07859D89194909F100D04588 /* Sources */, 07859D8A194909F100D04588 /* Frameworks */, 07859D8B194909F100D04588 /* Resources */, + 1E94C2A0A5C8349B333E9704 /* Embed Pods Frameworks */, + 3EE47F6AFF8F1BB00D604605 /* Copy Pods Resources */, ); buildRules = ( ); @@ -219,18 +280,112 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 1E94C2A0A5C8349B333E9704 /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftJsonTests/Pods-SwiftJsonTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3EE47F6AFF8F1BB00D604605 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftJsonTests/Pods-SwiftJsonTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 453E0CC42F5EABAB3D4938E7 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 5A84E93669C8A8F442893764 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + A0FA70CE020EE0F646699F1B /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftJson/Pods-SwiftJson-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + DC6D376FAB568EF83785D6BF /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftJson/Pods-SwiftJson-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 07859D75194909F000D04588 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 07859D83194909F100D04588 /* AppDelegate.swift in Sources */, + B27E45941AFEB97100D7EC8D /* Generator.swift in Sources */, 07859D81194909F100D04588 /* ViewController.swift in Sources */, + B2D403181AF8CC5D0088E073 /* ClassModel.swift in Sources */, 07859D7F194909F100D04588 /* main.swift in Sources */, - 07859DA019490AAE00D04588 /* IndentableOutput.swift in Sources */, + B2D403231AF922340088E073 /* JSONUtils.swift in Sources */, + B2A978201AF6B02300B2BC8C /* NSScanner+Swift.swift in Sources */, 07859DA219491CD500D04588 /* MenuController.swift in Sources */, - 073B4B53196B7D5000A62AF4 /* SwiftyJSON.swift in Sources */, - 07859D9E19490A9A00D04588 /* ModelGenerator.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -238,8 +393,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 07859D94194909F100D04588 /* SwiftJsonTests.swift in Sources */, - 073B4B54196B7D5000A62AF4 /* SwiftyJSON.swift in Sources */, + B27E45951AFED26D00D7EC8D /* Generator.swift in Sources */, + B2D403261AF9233C0088E073 /* JSONUtils.swift in Sources */, + B2D403251AF922DF0088E073 /* JSONUtilsTests.swift in Sources */, + B2D403191AF904CE0088E073 /* ClassModel.swift in Sources */, + B2D403211AF921A30088E073 /* ClassModelTests.swift in Sources */, + B2D403161AF822970088E073 /* GeneratorTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -344,30 +503,43 @@ }; 07859D98194909F100D04588 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 35A74A846D9D4D51C11FB2D4 /* Pods-SwiftJson.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/build/Debug-iphoneos/Pods-SwiftJsonTests", + "$(PROJECT_DIR)/build/Debug-iphoneos/Pods-SwiftJson", + ); INFOPLIST_FILE = SwiftJson/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 07859D99194909F100D04588 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = C1733AEA159B850EADA5D67D /* Pods-SwiftJson.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/build/Debug-iphoneos/Pods-SwiftJsonTests", + "$(PROJECT_DIR)/build/Debug-iphoneos/Pods-SwiftJson", + ); INFOPLIST_FILE = SwiftJson/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 07859D9B194909F100D04588 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 80BD305520F4EFFE3B982A84 /* Pods-SwiftJsonTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftJson.app/Contents/MacOS/SwiftJson"; COMBINE_HIDPI_IMAGES = YES; @@ -381,6 +553,7 @@ ); INFOPLIST_FILE = SwiftJsonTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; METAL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; @@ -389,6 +562,7 @@ }; 07859D9C194909F100D04588 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0AF4D90A355893C0CEE0EE37 /* Pods-SwiftJsonTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftJson.app/Contents/MacOS/SwiftJson"; COMBINE_HIDPI_IMAGES = YES; @@ -398,6 +572,7 @@ ); INFOPLIST_FILE = SwiftJsonTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; METAL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; diff --git a/SwiftJson.xcodeproj/project.xcworkspace/xcshareddata/SwiftJson.xccheckout b/SwiftJson.xcodeproj/project.xcworkspace/xcshareddata/SwiftJson.xccheckout new file mode 100644 index 0000000..da7ff87 --- /dev/null +++ b/SwiftJson.xcodeproj/project.xcworkspace/xcshareddata/SwiftJson.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 12987391-4943-4B97-9A90-9E5DDF62779A + IDESourceControlProjectName + SwiftJson + IDESourceControlProjectOriginsDictionary + + 957C2411939784F97902D82EAC722A5A882F3E35 + https://github.com/kungfurorykelly/SwiftJson.git + + IDESourceControlProjectPath + SwiftJson.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + 957C2411939784F97902D82EAC722A5A882F3E35 + ../.. + + IDESourceControlProjectURL + https://github.com/kungfurorykelly/SwiftJson.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 957C2411939784F97902D82EAC722A5A882F3E35 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 957C2411939784F97902D82EAC722A5A882F3E35 + IDESourceControlWCCName + SwiftJson + + + + diff --git a/SwiftJson.xcworkspace/contents.xcworkspacedata b/SwiftJson.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..b0dc237 --- /dev/null +++ b/SwiftJson.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/SwiftJson.xcworkspace/xcshareddata/SwiftJson.xccheckout b/SwiftJson.xcworkspace/xcshareddata/SwiftJson.xccheckout new file mode 100644 index 0000000..ccb9c00 --- /dev/null +++ b/SwiftJson.xcworkspace/xcshareddata/SwiftJson.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + BCAF5E1C-AB78-4B1E-A440-02B5C252440C + IDESourceControlProjectName + SwiftJson + IDESourceControlProjectOriginsDictionary + + 957C2411939784F97902D82EAC722A5A882F3E35 + https://github.com/kungfurorykelly/SwiftJson.git + + IDESourceControlProjectPath + SwiftJson.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 957C2411939784F97902D82EAC722A5A882F3E35 + .. + + IDESourceControlProjectURL + https://github.com/kungfurorykelly/SwiftJson.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 957C2411939784F97902D82EAC722A5A882F3E35 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 957C2411939784F97902D82EAC722A5A882F3E35 + IDESourceControlWCCName + SwiftJson + + + + diff --git a/SwiftJson/ClassModel.swift b/SwiftJson/ClassModel.swift new file mode 100644 index 0000000..2768c2d --- /dev/null +++ b/SwiftJson/ClassModel.swift @@ -0,0 +1,89 @@ +// +// ClassModel.swift +// SwiftJson +// +// Created by RORY KELLY on 05/05/2015. +// Copyright (c) 2015 pvwoods. All rights reserved. +// + +import Foundation +import SwiftyJSON + +/** +Model to hold definition of classes +*/ +struct ClassModel { + static let CLASS_PLACEHOLDER = "*CLASS*" + static let VARIABLES_PLACEHOLDER = "*VARIABLES*" + static let MAPPING_PLACEHOLDER = "*MAPPINGS*" + static let classStructure = + "\nclass *CLASS* : Mappable { " + + "\n *VARIABLES*" + + "\n required init?(_ map: Map){" + + "\n mapping(map)" + + "\n }\n" + + "\n func mapping(map: Map) {" + + "\n *MAPPINGS*" + + "\n }" + + " \n}" + + let className:String + let variables:[String:String] + + init(name:String, objectDictionary:[String:JSON]){ + className = name; + variables = ClassModel.getTypes(objectDictionary) + } + + func generateDescription() -> String { + var variablesString = "" + var mappingString = "" + for(name, type) in variables { + variablesString = variablesString.stringByAppendingString("var " + name + ":" + type + "? \n ") + mappingString = mappingString.stringByAppendingString(name + " <- map[\"" + name + "\"] \n ") + } + return ClassModel.classStructure + .stringByReplacingOccurrencesOfString(ClassModel.CLASS_PLACEHOLDER, withString: className) + .stringByReplacingOccurrencesOfString(ClassModel.VARIABLES_PLACEHOLDER, withString: variablesString) + .stringByReplacingOccurrencesOfString(ClassModel.MAPPING_PLACEHOLDER, withString: mappingString) + } + + /** + get the types associated with a dictionary. + :param: dictionary of types in json + :returns: map [name:type] + */ + static func getTypes(objectDictionary:[String:JSON]) -> [String:String]{ + var variables:[String:String] = [:] + // save all of the types + for(variableName, json) in objectDictionary { + // variable names are guaranteed to be unique at this point. + // save a map of object type to name. + variables[variableName] = ClassModel.getType(variableName, jsonObject: json) + } + return variables + } + + /** + get the type of a single JSON pairing + :param: key for json object. + :param: json object to get types for. + :returns: a string representing the type for a type. + */ + static func getType(key:String, jsonObject:JSON) -> String { + switch (jsonObject.type) { + case .String: + return "String" + case .Number: + return "Double" + case .Bool: + return "Bool" + case .Array: + return "[" + getType(key, jsonObject: jsonObject[0]) + "]" + case .Dictionary: + return key + default: + return "AnyObject" + } + } +} \ No newline at end of file diff --git a/SwiftJson/Generator.swift b/SwiftJson/Generator.swift new file mode 100644 index 0000000..f22147c --- /dev/null +++ b/SwiftJson/Generator.swift @@ -0,0 +1,64 @@ +// +// Generator.swift +// SwiftJson +// +// Created by RORY KELLY on 09/05/2015. +// Copyright (c) 2015 pvwoods. All rights reserved. +// + +import Foundation +import SwiftyJSON + +class Generator { + + private let rootObject:JSON + + init(jsonObject:JSON){ + rootObject = jsonObject + } + + static func getAllDictionaries(object:JSON, function:(String,[String : JSON]) -> ()) { + for (key: String, subJson: JSON) in object { + if (subJson.type == .Dictionary) { + function(key, subJson.dictionaryValue) + getAllDictionaries(subJson, function: function); + } else if (subJson.type == .Array) { + if(subJson[0].type == .Dictionary){ + function(key, subJson[0].dictionaryValue) + getAllDictionaries(subJson[0], function: function) + } + } + } + } + + func getAllClassModels() -> [ClassModel] { + var classModels:[ClassModel] = [] + if (rootObject.type == .Dictionary) { + classModels.append(ClassModel(name: "rootClass", objectDictionary: rootObject.dictionaryValue)) + } else if (rootObject.type == .Array) { + if(rootObject[0].type == .Dictionary){ + Generator.getAllDictionaries(rootObject, function: { (name, dictionary) -> () in + classModels.append(ClassModel(name: name, objectDictionary: dictionary)) + }) + return classModels + } + } + + Generator.getAllDictionaries(rootObject, function: { (name, dictionary) -> () in + classModels.append(ClassModel(name: name, objectDictionary: dictionary)) + }) + return classModels + } + + func getFinalOutput() -> String { + let classModels = getAllClassModels() + var finalOutput = "" + for classModel in classModels { + finalOutput = finalOutput.stringByAppendingString(classModel.generateDescription()) + } + return finalOutput + } + + + +} \ No newline at end of file diff --git a/SwiftJson/IndentableOutput.swift b/SwiftJson/IndentableOutput.swift deleted file mode 100644 index 10699b9..0000000 --- a/SwiftJson/IndentableOutput.swift +++ /dev/null @@ -1,109 +0,0 @@ -// -// IndentableOutput.swift -// swiftin -// -// Created by Philip Woods on 6/11/14. -// Copyright (c) 2014 pvwoods. All rights reserved. -// - -import Foundation - -enum OutputInstructionType:Int { - case Indent - case PrintLine -} - -struct OutputInstruction { - var type:OutputInstructionType - var data:AnyObject - - init(iType:OutputInstructionType, iData:AnyObject) { - self.type = iType - self.data = iData - } -} - -class IndentableOutput { - - let spacesPerIndent:Int = 4 - - var _indentation:Int = 0 - var indentation:Int { - get { - return _indentation - } - set { - let i:Int = newValue - _indentation; - _indentation = newValue - rawOutput.append(OutputInstruction(iType: OutputInstructionType.Indent, iData: i)) - } - } - var tabs:String { - get { - return " " * (indentation * spacesPerIndent) - } - } - - var output:String = "" - var rawOutput:[OutputInstruction] = [] - - func addLineToOutput(l:String) -> IndentableOutput { - rawOutput.append(OutputInstruction(iType: OutputInstructionType.PrintLine, iData: l)) - output += tabs + l + "\n" - return self - } - - func indent() -> IndentableOutput { - self.indentation++ - return self - } - - func dedent() -> IndentableOutput { - self.indentation-- - return self - } - -} - - func + (left:IndentableOutput, right:IndentableOutput) -> IndentableOutput { - - for instruction in right.rawOutput { - switch instruction.type { - case OutputInstructionType.Indent: - left.indentation += instruction.data as Int - case OutputInstructionType.PrintLine: - left.addLineToOutput(instruction.data as String) - } - } - - return left -} - - func += (left:IndentableOutput, right:IndentableOutput) -> IndentableOutput { - return left + right -} - - func + (left:IndentableOutput, right:String) -> IndentableOutput { - left.addLineToOutput(right) - return left -} - - func += (left:IndentableOutput, right:String) -> IndentableOutput { - left.addLineToOutput(right) - return left -} - - func += (left:IndentableOutput, right:[IndentableOutput]) -> IndentableOutput { - for io in right { - left += io - } - return left -} - - func * (left: String, right: Int) -> String { - var output = left - for i in 0...right { - output += left - } - return output -} diff --git a/SwiftJson/JSONUtils.swift b/SwiftJson/JSONUtils.swift new file mode 100644 index 0000000..6aa6163 --- /dev/null +++ b/SwiftJson/JSONUtils.swift @@ -0,0 +1,54 @@ +// +// JSONUtils.swift +// SwiftJson +// +// Created by RORY KELLY on 05/05/2015. +// Copyright (c) 2015 pvwoods. All rights reserved. +// + +import Foundation +import SwiftyJSON + +class JSONUtils { + /** + Validate a json string. + :param: validate a string. + :returns: Boolean. + */ + static func validateJSON(jsonText:String)-> Bool { + if let jsonData = stringToNSData(jsonText) { + var jsonError: NSError? + NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &jsonError) + if let unwrappedError = jsonError { + println("json error: \(unwrappedError)") + return false + } + return true + } + return false + } + + /** + convert a string to NSData. + :param: validate a string. + :returns: NSData. + */ + static func stringToNSData(jsonText:String)-> NSData? { + if let jsonData = (jsonText as NSString).dataUsingEncoding(NSUTF8StringEncoding) { + return jsonData + } + return .None + } + + /** + convert a string to a JSON object. + :param: validate a string. + :returns: SwiftyJSON. + */ + static func stringToJSON(jsonText:String)-> JSON? { + if let jsonData = (jsonText as NSString).dataUsingEncoding(NSUTF8StringEncoding) { + return JSON(data:jsonData) + } + return .None + } +} \ No newline at end of file diff --git a/SwiftJson/ModelGenerator.swift b/SwiftJson/ModelGenerator.swift deleted file mode 100644 index fb4c49a..0000000 --- a/SwiftJson/ModelGenerator.swift +++ /dev/null @@ -1,148 +0,0 @@ -// -// ModelGenerator.swift -// swiftin -// -// Created by Philip Woods on 6/11/14. -// Copyright (c) 2014 pvwoods. All rights reserved. -// - -import Foundation - -import Cocoa - - -class ModelGenerator { - - var modelOutput:IndentableOutput = IndentableOutput() - var childModels:[ModelGenerator] = [] - - var output:String { - get { - return modelOutput.output - } - } - - init(json:JSONValue, className:String, inspectArrays:Bool) { - - // set up the init function - var initOutput:IndentableOutput = IndentableOutput() - (initOutput += "init(json:JSONValue) {").indent() - - // model set up - (modelOutput += "class \(className) {").indent() - - // generate everything - switch(json) { - case .JArray(let array): - initOutput += "// initial element was array..." - case .JObject(let object): - for (key, value) in object { - - var type = "" - - switch value { - case .JString(let value): - type = "String" - buildSetStatement(initOutput, key:key, type:type) - case .JNumber(let value): - type = "NSNumber" - buildSetStatement(initOutput, key:key, type:type) - case .JBool(let value): - type = "Bool" - buildSetStatement(initOutput, key:key, type:type) - case .JArray(let array): - if(inspectArrays && array.count >= 1) { - type = handleArray(array, key: key, className: className, inspectArrays: inspectArrays, io: initOutput) - } else { - initOutput += "\(key) = json[\"\(key)\"]" - } - case .JObject(let object): - var cn = self.buildClassName(className, suffix: key as String) - childModels.append(ModelGenerator(json: value, className: cn, inspectArrays:inspectArrays)) - type = cn - initOutput += "\(key) = \(type)(json:json[\"\(key)\"])" - default: - type = "AnyObject" - } - - modelOutput += "var \(key):\(type)" - } - default: - initOutput += "// unexpected type encountered" - } - - // merge the init function and close everything up - modelOutput += initOutput - - // close everything up - (modelOutput.dedent() += "}").dedent() += "}" - - // append any child models - for child in childModels { - self.modelOutput += child.modelOutput - } - - } - - func handleArray(array:Array, key:String, className:String, inspectArrays:Bool, io:IndentableOutput) -> String { - - var instantiation = "v" - var type = "[AnyObject]" - - switch array[0] { - case .JString(let value): - type = "[String]" - - case .JNumber(let value): - type = "[NSNumber]" - - case .JBool(let value): - type = "[Bool]" - - case .JArray(let arr): - type = "[JSONValue]" - case .JObject(let object): - var cn = buildClassName(className, suffix: key as String) - childModels.append(ModelGenerator(json: array[0], className: cn, inspectArrays:inspectArrays)) - type = "[" + cn + "]" - instantiation = "\(cn)(json:v)" - default: - type = "AnyObject" - } - - io += "\(key) = []" - (io += "if let xs = json[\"\(key)\"].array {").indent() - (io += "for v in xs {").indent() - (io += "\(key) += \(instantiation)").dedent() + "}" - io.dedent() += "}" - - return type - } - - func buildSetStatement(io:IndentableOutput, key:String, type:String) { - - let optionTypeMap = [ - "Bool": "bool", - "NSNumber": "number", - "String": "string" - ] - - let optionDefaultValueMap = [ - "Bool": "false", - "NSNumber": "0", - "String": "\"\"" - ] - - (io += "if let value = json[\"\(key)\"].\(optionTypeMap[type]) {").indent() - (((io += "\(key) = value").dedent()) += "} else {").indent() - (io += "\(key) = \(optionDefaultValueMap[type])").dedent() += "}" - - } - - func buildClassName(className:String, suffix:String) -> String { - let index: String.Index = advance(suffix.startIndex, 1) - var firstChar = (suffix as NSString).uppercaseString.substringToIndex(index) - return className + firstChar + (suffix as NSString).substringFromIndex(1) - } - -} diff --git a/SwiftJson/NSScanner+Swift.swift b/SwiftJson/NSScanner+Swift.swift new file mode 100644 index 0000000..cdffa23 --- /dev/null +++ b/SwiftJson/NSScanner+Swift.swift @@ -0,0 +1,154 @@ +// NSScanner+Swift.swift +// A set of Swift-idiomatic methods for NSScanner +// +// (c) 2015 Nate Cook, licensed under the MIT license + +import Foundation + +extension NSScanner { + + // MARK: Strings + + /// Returns a string, scanned as long as characters from a given character set are encountered, or `nil` if none are found. + func scanCharactersFromSet(set: NSCharacterSet) -> String? { + var value: NSString? = "" + if scanCharactersFromSet(set, intoString: &value), + let value = value as? String { + return value + } + return nil + } + + /// Returns a string, scanned until a character from a given character set are encountered, or the remainder of the scanner's string. Returns `nil` if the scanner is already `atEnd`. + func scanUpToCharactersFromSet(set: NSCharacterSet) -> String? { + var value: NSString? = "" + if scanUpToCharactersFromSet(set, intoString: &value), + let value = value as? String { + return value + } + return nil + } + + /// Returns the given string if scanned, or `nil` if not found. + func scanString(str: String) -> String? { + var value: NSString? = "" + if scanString(str, intoString: &value), + let value = value as? String { + return value + } + return nil + } + + /// Returns a string, scanned until the given string is found, or the remainder of the scanner's string. Returns `nil` if the scanner is already `atEnd`. + func scanUpToString(str: String) -> String? { + var value: NSString? = "" + if scanUpToString(str, intoString: &value), + let value = value as? String { + return value + } + return nil + } + + // MARK: Numbers + + /// Returns a Double if scanned, or `nil` if not found. + func scanDouble() -> Double? { + var value = 0.0 + if scanDouble(&value) { + return value + } + return nil + } + + /// Returns a Float if scanned, or `nil` if not found. + func scanFloat() -> Float? { + var value: Float = 0.0 + if scanFloat(&value) { + return value + } + return nil + } + + /// Returns an Int if scanned, or `nil` if not found. + func scanInteger() -> Int? { + var value = 0 + if scanInteger(&value) { + return value + } + return nil + } + + /// Returns an Int32 if scanned, or `nil` if not found. + func scanInt() -> Int32? { + var value: Int32 = 0 + if scanInt(&value) { + return value + } + return nil + } + + /// Returns an Int64 if scanned, or `nil` if not found. + func scanLongLong() -> Int64? { + var value: Int64 = 0 + if scanLongLong(&value) { + return value + } + return nil + } + + /// Returns a UInt64 if scanned, or `nil` if not found. + func scanUnsignedLongLong() -> UInt64? { + var value: UInt64 = 0 + if scanUnsignedLongLong(&value) { + return value + } + return nil + } + + /// Returns an NSDecimal if scanned, or `nil` if not found. + func scanDecimal() -> NSDecimal? { + var value = NSDecimal() + if scanDecimal(&value) { + return value + } + return nil + } + + // MARK: Hex Numbers + + /// Returns a Double if scanned in hexadecimal, or `nil` if not found. + func scanHexDouble() -> Double? { + var value = 0.0 + if scanHexDouble(&value) { + return value + } + return nil + } + + /// Returns a Float if scanned in hexadecimal, or `nil` if not found. + func scanHexFloat() -> Float? { + var value: Float = 0.0 + if scanHexFloat(&value) { + return value + } + return nil + } + + /// Returns a UInt32 if scanned in hexadecimal, or `nil` if not found. + func scanHexInt() -> UInt32? { + var value: UInt32 = 0 + if scanHexInt(&value) { + return value + } + return nil + } + + /// Returns a UInt64 if scanned in hexadecimal, or `nil` if not found. + func scanHexLongLong() -> UInt64? { + var value: UInt64 = 0 + if scanHexLongLong(&value) { + return value + } + return nil + } +} diff --git a/SwiftJson/SwiftyJSON.swift b/SwiftJson/SwiftyJSON.swift deleted file mode 100644 index ba7963d..0000000 --- a/SwiftJson/SwiftyJSON.swift +++ /dev/null @@ -1,425 +0,0 @@ -// SwiftyJSON.swift -// -// Copyright (c) 2014年 Ruoyu Fu, Denis Lebedev. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - - -public enum JSONValue { - - - case JNumber(NSNumber) - case JString(String) - case JBool(Bool) - case JNull - case JArray(Array) - case JObject(Dictionary) - case JInvalid(NSError) - - public var string: String? { - switch self { - case .JString(let value): - return value - default: - return nil - } - } - - public var url: NSURL? { - switch self { - case .JString(let value): - return NSURL(string: value) - default: - return nil - } - } - public var number: NSNumber? { - switch self { - case .JNumber(let value): - return value - default: - return nil - } - } - - public var double: Double? { - switch self { - case .JNumber(let value): - return value.doubleValue - case .JString(let value): - return (value as NSString).doubleValue - default: - return nil - } - } - - public var integer: Int? { - switch self { - case .JBool(let value): - return Int(value) - case .JNumber(let value): - return value.integerValue - case .JString(let value): - return (value as NSString).integerValue - default: - return nil - } - } - - public var bool: Bool? { - switch self { - case .JBool(let value): - return value - case .JNumber(let value): - return value.boolValue - case .JString(let value): - return (value as NSString).boolValue - default: - return nil - } - } - - public var array: Array? { - switch self { - case .JArray(let value): - return value - default: - return nil - } - } - - public var object: Dictionary? { - switch self { - case .JObject(let value): - return value - default: - return nil - } - } - - var any: AnyObject? { - switch self { - case .JNumber(let value): - return value - case .JString(let value): - return value - case .JBool(let value): - return value - case .JNull: - return NSNull() - case .JArray(let value): - var jsonValues = [AnyObject]() - for alreadyJsonValue in value { - if let jsonValue: AnyObject? = alreadyJsonValue.any { - jsonValues.append(jsonValue!) - } - } - return jsonValues - case .JObject(let value): - var jsonObject = Dictionary() - for (alreadyJsonKey : String, alreadyJsonValue : JSONValue) in value { - if let jsonValue: AnyObject? = alreadyJsonValue.any { - jsonObject[alreadyJsonKey] = jsonValue! - } - } - return jsonObject - default: - return nil - } - } - - - public var first: JSONValue? { - switch self { - case .JArray(let jsonArray) where jsonArray.count > 0: - return jsonArray[0] - case .JObject(let jsonDictionary) where jsonDictionary.count > 0 : - let (_, value) = jsonDictionary[jsonDictionary.startIndex] - return value - default: - return nil - } - } - - public var last: JSONValue? { - switch self { - case .JArray(let jsonArray) where jsonArray.count > 0: - return jsonArray[jsonArray.count-1] - case .JObject(let jsonDictionary) where jsonDictionary.count > 0 : - let (_, value) = jsonDictionary[jsonDictionary.endIndex] - return value - default: - return nil - } - } - - public init (_ data: NSData!){ - if let value = data{ - var error:NSError? = nil - if let jsonObject : AnyObject = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) { - self = JSONValue(jsonObject) - }else{ - self = JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey:"JSON Parser Error: Invalid Raw JSON Data"])) - } - }else{ - self = JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1000, userInfo: [NSLocalizedDescriptionKey:"JSON Init Error: Invalid Value Passed In init()"])) - } - - } - - public init (_ rawObject: AnyObject) { - switch rawObject { - case let value as NSNumber: - if String.fromCString(value.objCType) == "c" { - self = .JBool(value.boolValue) - return - } - self = .JNumber(value) - case let value as NSString: - self = .JString(value) - case let value as NSNull: - self = .JNull - case let value as NSArray: - var jsonValues = [JSONValue]() - for possibleJsonValue : AnyObject in value { - let jsonValue = JSONValue(possibleJsonValue) - if jsonValue { - jsonValues.append(jsonValue) - } - } - self = .JArray(jsonValues) - case let value as NSDictionary: - var jsonObject = Dictionary() - for (possibleJsonKey : AnyObject, possibleJsonValue : AnyObject) in value { - if let key = possibleJsonKey as? NSString { - let jsonValue = JSONValue(possibleJsonValue) - if jsonValue { - jsonObject[key] = jsonValue - } - } - } - self = .JObject(jsonObject) - default: - self = .JInvalid(NSError(domain: "JSONErrorDomain", code: 1000, userInfo: [NSLocalizedDescriptionKey:"JSON Init Error: Invalid Value Passed In init()"])) - } - } - - public subscript(index: Int) -> JSONValue { - get { - switch self { - case .JArray(let jsonArray) where jsonArray.count > index: - return jsonArray[index] - case .JInvalid(let error): - if let userInfo = error.userInfo{ - if let breadcrumb = userInfo["JSONErrorBreadCrumbKey"] as? NSString{ - let newBreadCrumb = (breadcrumb as String) + "/\(index)" - let newUserInfo = [NSLocalizedDescriptionKey: "JSON Keypath Error: Incorrect Keypath \"\(newBreadCrumb)\"", - "JSONErrorBreadCrumbKey": newBreadCrumb] - return JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1002, userInfo: newUserInfo)) - } - } - return self - default: - let breadcrumb = "\(index)" - let newUserInfo = [NSLocalizedDescriptionKey: "JSON Keypath Error: Incorrect Keypath \"\(breadcrumb)\"", - "JSONErrorBreadCrumbKey": breadcrumb] - return JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1002, userInfo: newUserInfo)) - } - } - } - - public subscript(key: String) -> JSONValue { - get { - switch self { - case .JObject(let jsonDictionary): - if let value = jsonDictionary[key] { - return value - }else { - let breadcrumb = "\(key)" - let newUserInfo = [NSLocalizedDescriptionKey: "JSON Keypath Error: Incorrect Keypath \"\(breadcrumb)\"", - "JSONErrorBreadCrumbKey": breadcrumb] - return JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1002, userInfo: newUserInfo)) - } - case .JInvalid(let error): - if let userInfo = error.userInfo{ - if let breadcrumb = userInfo["JSONErrorBreadCrumbKey"] as? NSString{ - let newBreadCrumb = (breadcrumb as String) + "/\(key)" - let newUserInfo = [NSLocalizedDescriptionKey: "JSON Keypath Error: Incorrect Keypath \"\(newBreadCrumb)\"", - "JSONErrorBreadCrumbKey": newBreadCrumb] - return JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1002, userInfo: newUserInfo)) - } - } - return self - default: - let breadcrumb = "/\(key)" - let newUserInfo = [NSLocalizedDescriptionKey: "JSON Keypath Error: Incorrect Keypath \"\(breadcrumb)\"", - "JSONErrorBreadCrumbKey": breadcrumb] - return JSONValue.JInvalid(NSError(domain: "JSONErrorDomain", code: 1002, userInfo: newUserInfo)) - } - } - } -} - -extension JSONValue: Printable { - public var description: String { - switch self { - case .JInvalid(let error): - return error.localizedDescription - default: - return printableString("") - } - } - - public var rawJSONString: String { - switch self { - case .JNumber(let value): - return "\(value)" - case .JBool(let value): - return "\(value)" - case .JString(let value): - let jsonAbleString = value.stringByReplacingOccurrencesOfString("\"", withString: "\\\"", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil) - return "\"\(jsonAbleString)\"" - case .JNull: - return "null" - case .JArray(let array): - var arrayString = "" - for (index, value) in enumerate(array) { - if index != array.count - 1 { - arrayString += "\(value.rawJSONString)," - }else{ - arrayString += "\(value.rawJSONString)" - } - } - return "[\(arrayString)]" - case .JObject(let object): - var objectString = "" - var (index, count) = (0, object.count) - for (key, value) in object { - if index != count - 1 { - objectString += "\"\(key)\":\(value.rawJSONString)," - } else { - objectString += "\"\(key)\":\(value.rawJSONString)" - } - index += 1 - } - return "{\(objectString)}" - case .JInvalid: - return "INVALID_JSON_VALUE" - } - } - - private func printableString(indent: String) -> String { - switch self { - case .JObject(let object): - var objectString = "{\n" - var index = 0 - for (key, value) in object { - let valueString = value.printableString(indent + " ") - if index != object.count - 1 { - objectString += "\(indent) \"\(key)\":\(valueString),\n" - } else { - objectString += "\(indent) \"\(key)\":\(valueString)\n" - } - index += 1 - } - objectString += "\(indent)}" - return objectString - case .JArray(let array): - var arrayString = "[\n" - for (index, value) in enumerate(array) { - let valueString = value.printableString(indent + " ") - if index != array.count - 1 { - arrayString += "\(indent) \(valueString),\n" - }else{ - arrayString += "\(indent) \(valueString)\n" - } - } - arrayString += "\(indent)]" - return arrayString - default: - return rawJSONString - } - } -} - -extension JSONValue: BooleanType { - public var boolValue: Bool { - switch self { - case .JInvalid: - return false - default: - return true - } - } -} - -extension JSONValue : Equatable { - -} - -public func ==(lhs: JSONValue, rhs: JSONValue) -> Bool { - switch lhs { - case .JNumber(let lvalue): - switch rhs { - case .JNumber(let rvalue): - return rvalue == lvalue - default: - return false - } - case .JString(let lvalue): - switch rhs { - case .JString(let rvalue): - return rvalue == lvalue - default: - return false - } - case .JBool(let lvalue): - switch rhs { - case .JBool(let rvalue): - return rvalue == lvalue - default: - return false - } - case .JNull: - switch rhs { - case .JNull: - return true - default: - return false - } - case .JArray(let lvalue): - switch rhs { - case .JArray(let rvalue): - return rvalue == lvalue - default: - return false - } - case .JObject(let lvalue): - switch rhs { - case .JObject(let rvalue): - return rvalue == lvalue - default: - return false - } - default: - return false - } -} diff --git a/SwiftJson/ViewController.swift b/SwiftJson/ViewController.swift index e15d7dc..6b39d9c 100644 --- a/SwiftJson/ViewController.swift +++ b/SwiftJson/ViewController.swift @@ -7,6 +7,7 @@ // import Cocoa +import SwiftyJSON class ViewController: NSViewController { @@ -17,13 +18,13 @@ class ViewController: NSViewController { var jsonTextView : NSTextView { get { - return jsonScrollView.contentView.documentView as NSTextView + return jsonScrollView.contentView.documentView as! NSTextView } } var modelTextView : NSTextView { get { - return modelScrollView.contentView.documentView as NSTextView + return modelScrollView.contentView.documentView as! NSTextView } } @@ -52,25 +53,22 @@ class ViewController: NSViewController { var className = classNameTextField.stringValue.isEmpty ? "MyClass":classNameTextField.stringValue; - var jsonText = jsonTextView.textStorage.string - var jsonData = (jsonText as NSString).dataUsingEncoding(NSUTF8StringEncoding) + var jsonText = jsonTextView.textStorage!.string + var jsonData:NSData? = (jsonText as NSString).dataUsingEncoding(NSUTF8StringEncoding) if jsonData != nil { - let json = JSONValue(jsonData) + let json:JSON = JSON(data: jsonData!) - if json { - - let generator:ModelGenerator = ModelGenerator(json:json, className:className, inspectArrays:inspectArrays.state == 1) - - modelTextView.textStorage.setAttributedString(NSAttributedString(string: generator.output)) - + if json.type != .Unknown && json.type != .Null { + let generator = Generator(jsonObject: json) + modelTextView.textStorage!.setAttributedString(NSAttributedString(string:generator.getFinalOutput())) } else { - modelTextView.textStorage.setAttributedString(NSAttributedString(string:"There was an issue parsing your JSON...")) + modelTextView.textStorage!.setAttributedString(NSAttributedString(string:"There was an issue parsing your JSON...")) } } else { - modelTextView.textStorage.setAttributedString(NSAttributedString(string:"Couldn't encode your data...")) + modelTextView.textStorage!.setAttributedString(NSAttributedString(string:"Couldn't encode your data...")) } diff --git a/SwiftJson/main.swift b/SwiftJson/main.swift index e462d20..1806e0d 100644 --- a/SwiftJson/main.swift +++ b/SwiftJson/main.swift @@ -8,4 +8,4 @@ import Cocoa -NSApplicationMain(C_ARGC, C_ARGV) +NSApplicationMain(Process.argc, Process.unsafeArgv) diff --git a/SwiftJsonTests/ClassModelTests.swift b/SwiftJsonTests/ClassModelTests.swift new file mode 100644 index 0000000..68c6785 --- /dev/null +++ b/SwiftJsonTests/ClassModelTests.swift @@ -0,0 +1,48 @@ +// +// ClassModelTests.swift +// SwiftJson +// +// Created by RORY KELLY on 05/05/2015. +// Copyright (c) 2015 pvwoods. All rights reserved. +// + +import Foundation +import XCTest +import SwiftyJSON + +class ClassModelTests: XCTestCase { + static let simpleJSON = "{ \"title\": \"Example Schema\", \"type\": \"object\", \"properties\": { \"firstName\": { \"type\": \"string\" }, \"lastName\": { \"type\": \"string\" }, \"age\": { \"description\": \"Age in years\", \"type\": \"integer\", \"minimum\": 0 } }, \"required\": [\"firstName\", \"lastName\"] }" + var classModel:ClassModel? + var json:JSON?; + + override func setUp() { + super.setUp() + json = JSONUtils.stringToJSON(ClassModelTests.simpleJSON) + // Put setup code here. This method is called before the invocation of each test method in the class. + classModel = ClassModel(name: "className", objectDictionary: json!.dictionary!) + } + + override func tearDown() { + super.tearDown() + classModel = .None + } + + func testGenerateDescription() { + classModel!.generateDescription() + } + + func testGetTypes() { + var nameType = ClassModel.getTypes(json!.dictionary!) + XCTAssertEqual(nameType.count, 4, "PASS") + XCTAssertEqual(nameType["title"]!, "String","PASS") + XCTAssertEqual(nameType["type"]!, "String","PASS") + XCTAssertEqual(nameType["properties"]!, "properties","PASS") + XCTAssertEqual(nameType["required"]!, "[String]","PASS") + } + + + func testGetType() { + XCTAssertEqual(ClassModel.getType("title", jsonObject: json!["title"]), "String") + } + +} \ No newline at end of file diff --git a/SwiftJsonTests/GeneratorTests.swift b/SwiftJsonTests/GeneratorTests.swift new file mode 100644 index 0000000..03dab60 --- /dev/null +++ b/SwiftJsonTests/GeneratorTests.swift @@ -0,0 +1,77 @@ +// +// GenTests.swift +// SwiftJson +// +// Created by RORY KELLY on 04/05/2015. +// Copyright (c) 2015 pvwoods. All rights reserved. +// + +import Foundation + +import XCTest +import SwiftyJSON + +class GeneratorTests: XCTestCase { + static let simpleJSON = "{ \"title\": \"Example Schema\", \"type\": \"object\", \"properties\": { \"firstName\": { \"type\": \"string\" }, \"lastName\": { \"type\": \"string\" }, \"age\": { \"description\": \"Age in years\", \"type\": \"integer\", \"minimum\": 0 } }, \"required\": [\"firstName\", \"lastName\"] }" + var generator:Generator?; + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + generator = Generator(jsonObject: JSONUtils.stringToJSON(GeneratorTests.simpleJSON)!) + } + + override func tearDown() { + super.tearDown() + generator = .None + } + + func testGetAllDictionaries() { + var json:JSON? = JSONUtils.stringToJSON(GeneratorTests.simpleJSON) + var count = 0 + Generator.getAllDictionaries(json!) { (string, [String : JSON]) -> () in + ++count + } + XCTAssertEqual(count, 4, "PASS") + } + + func testGetAllClassModels(){ + let result = generator!.getAllClassModels() + // first check that we have the right number of classes + XCTAssertEqual(result.count, 5, "PASS") + + // look at the root class first. + XCTAssertEqual(result[0].variables.count, 4,"PASS") + XCTAssertEqual(result[0].variables["title"]!, "String","PASS") + XCTAssertEqual(result[0].variables["type"]!, "String","PASS") + XCTAssertEqual(result[0].variables["properties"]!, "properties","PASS") + XCTAssertEqual(result[0].variables["required"]!, "[String]","PASS") + + XCTAssertEqual(result[1].className, "properties", "PASS") + XCTAssertEqual(result[1].variables["age"]!, "age", "PASS") + XCTAssertEqual(result[1].variables["firstName"]!, "firstName", "PASS") + XCTAssertEqual(result[1].variables["lastName"]!, "lastName", "PASS") + + XCTAssertEqual(result[2].className, "age", "PASS") + XCTAssertEqual(result[2].variables["type"]!, "String", "PASS") + XCTAssertEqual(result[2].variables["minimum"]!, "Double", "PASS") + XCTAssertEqual(result[2].variables["description"]!, "String", "PASS") + + XCTAssertEqual(result[3].className, "firstName", "PASS") + XCTAssertEqual(result[3].variables["type"]!, "String", "PASS") + + XCTAssertEqual(result[4].className, "lastName", "PASS") + XCTAssertEqual(result[4].variables["type"]!, "String", "PASS") + + } + + func testGetClassRepresentation() { + let classes = generator!.getAllClassModels() + for classString in classes { + println(classString) + } + + } + + +} \ No newline at end of file diff --git a/SwiftJsonTests/JSONUtilsTests.swift b/SwiftJsonTests/JSONUtilsTests.swift new file mode 100644 index 0000000..eb054b1 --- /dev/null +++ b/SwiftJsonTests/JSONUtilsTests.swift @@ -0,0 +1,41 @@ +// +// JSONUtilsTests.swift +// SwiftJson +// +// Created by RORY KELLY on 05/05/2015. +// Copyright (c) 2015 pvwoods. All rights reserved. +// + +import Foundation +import XCTest +import SwiftyJSON + +class JSONUtilsTests: XCTestCase { + static let simpleJSON = "{ \"title\": \"Example Schema\", \"type\": \"object\", \"properties\": { \"firstName\": { \"type\": \"string\" }, \"lastName\": { \"type\": \"string\" }, \"age\": { \"description\": \"Age in years\", \"type\": \"integer\", \"minimum\": 0 } }, \"required\": [\"firstName\", \"lastName\"] }" + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testSringToData() { + XCTAssertNotNil(JSONUtils.stringToNSData(JSONUtilsTests.simpleJSON), "Pass") + } + + func testValidator() { + // This is an example of a functional test case. + XCTAssert(JSONUtils.validateJSON(JSONUtilsTests.simpleJSON), "Pass") + } + + func testGetAllDictionaries() { + var json:JSON? = JSONUtils.stringToJSON(JSONUtilsTests.simpleJSON) + var count = 0 + Generator.getAllDictionaries(json!) { (string, [String : JSON]) -> () in + ++count + } + XCTAssertEqual(count, 4, "PASS") + } +} \ No newline at end of file diff --git a/SwiftJsonTests/SwiftJsonTests.swift b/SwiftJsonTests/SwiftJsonTests.swift deleted file mode 100644 index f58534d..0000000 --- a/SwiftJsonTests/SwiftJsonTests.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// SwiftJsonTests.swift -// SwiftJsonTests -// -// Created by Philip Woods on 6/11/14. -// Copyright (c) 2014 pvwoods. All rights reserved. -// - -import XCTest - -class SwiftJsonTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - XCTAssert(true, "Pass") - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measureBlock() { - // Put the code you want to measure the time of here. - } - } - -}