Last active
August 29, 2015 14:23
-
-
Save jeremychone/70e8143883c01a6946b4 to your computer and use it in GitHub Desktop.
Simple and convenient Json wrapper for the AnyObject returned by NSJSONSerialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
// | |
// Json.swift | |
// | |
// Simple and convenient JSON wrapper of a AnyObject returned by the NSJSONSerialization parser. | |
// | |
// NEXT: probably want to split the promise (done/fail) from the future part (the resolve/reject) | |
// | |
// Jeremy Chone 2015-06-21 | |
public class Json : CustomStringConvertible{ | |
enum JsonError: ErrorType{ | |
case CANT_PARSE(ErrorType) | |
} | |
let jsonObject: AnyObject | |
public var description: String { get { | |
return (jsonObject.description)! | |
}} | |
// --------- Constructors & Factories --------- // | |
public init(jsonObject: AnyObject){ | |
self.jsonObject = jsonObject | |
} | |
static public func parse(jsonString jsonString: String) throws -> Json{ | |
do{ | |
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding) | |
let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.AllowFragments) | |
return Json(jsonObject: jsonObject) | |
} catch let e { | |
throw JsonError.CANT_PARSE(e) | |
} | |
} | |
// --------- /Constructors & Factories --------- // | |
// --------- Subscripts --------- // | |
// Convenience for get(:[String]). | |
// e.g. json["username"] or json["company","name"] | |
public subscript(names: String...) -> Json? { | |
return get(names) | |
} | |
// --------- /Subscripts --------- // | |
// --------- Public APIs --------- // | |
// Possibly return a new Json object targeted by a list of names for the path | |
public func get(names: [String]) -> Json?{ | |
// if empty names, we can shortcut and return self | |
if (names.isEmpty){ | |
return self; | |
} | |
// attempt to get the anyObject for this path names | |
guard let obj = anyObject(names) else{ | |
return nil | |
} | |
// create and return the new Json object only if found | |
return Json(jsonObject: obj) | |
} | |
// variadic convenience | |
public func get(names: String...) -> Json?{ | |
return get(names); | |
} | |
// If the targeted jsonObject is an [AnyObject], this will map it to a [Json] | |
public func array(names: String...) -> [Json]? { | |
guard let objs = anyObject(names) as? [AnyObject] else { | |
return nil | |
} | |
return objs.map({Json(jsonObject:$0)}) | |
} | |
// convenience method for get(names) as? String | |
public func string(names: String...) -> String?{ | |
return anyObject(names) as? String | |
} | |
// convenience method for get(names) as? Int | |
public func int(names: String...) -> Int?{ | |
return anyObject(names) as? Int | |
} | |
// convenience method for get(names) as? Double | |
public func double(names: String...) -> Double?{ | |
return anyObject(names) as? Double | |
} | |
// convenience method for get(names) as? Boolean | |
public func bool(names: String...) -> Bool?{ | |
return anyObject(names) as? Bool | |
} | |
// Possibly return an AnyObject targetted by the set of names | |
// If names is an empty array, returns this json AnyObject | |
// e.g. to get "company.name" AnyObject?, you call anyObject(["company","name"]) | |
public func anyObject(names: [String]) -> AnyObject?{ | |
var currentObj: AnyObject? = jsonObject | |
if names.isEmpty { | |
return currentObj | |
} | |
for path in names { | |
guard let dic = currentObj as? Dictionary<String,AnyObject> else { | |
currentObj = nil | |
break | |
} | |
currentObj = dic[path] | |
if (currentObj == nil){ | |
break; | |
} | |
} | |
return currentObj; | |
} | |
// Variadic convenience to allow the anyObject("company","name") | |
public func anyObject(names: String...) -> AnyObject?{ | |
return anyObject(names) | |
} | |
// --------- /Public APIs --------- // | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: [Previous](@previous) | |
import Foundation | |
import XCPlayground | |
let filePath = NSBundle.mainBundle().pathForResource("playground-test", ofType: "json") | |
// get the contentData | |
let contentData = NSFileManager.defaultManager().contentsAtPath(filePath!) | |
// get the string | |
let jsonString = NSString(data: contentData!, encoding: NSUTF8StringEncoding) as? String | |
//print("filepath: \(filePath!)") | |
//if let c = jsonString { | |
// print("content: \n\(c)") | |
//} | |
do { | |
let json = try Json.parse(jsonString: jsonString!) | |
if let val = json.anyObject("username") as? String{ | |
print(val) | |
} | |
print(json.int("id")!) | |
print("--- json.username") | |
print(json.string("username")) | |
print(json.get("username")?.string()) | |
print(json["username"]?.string()) | |
print(json["username","name"]) // should return nil | |
print("--- json.company.name") | |
print(json["company","name"]) | |
print(json["company"]?["name"]) | |
print("--- json.company.address.zipcode") | |
print(json["company"]?["address"]?["zipcode"]) | |
print(json["company","address","zipcode"]?.int()) | |
print(json["company","address","zipcode"]?.double()) | |
print(json["company","address","zipcode"]?.string()) | |
print("--- json.company.address.hq") | |
print(json["company"]?["address"]?["hq"]) | |
print(json["company"]?["address"]?["hq"]?.get()) | |
print(json["company"]?["address"]?["hq"]?.bool()) | |
print(json.bool("company","address","hq")) | |
print(json["company"]?["address"]?["hq"]?.anyObject() as? Bool) | |
print("--- json.languages") | |
let jlanguages = json["languages"]?.array() | |
print(jlanguages?[0].string("name")) | |
} catch let e { | |
print("Playground Error \(e)") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
jc | |
123 | |
--- json.username | |
Optional("jc") | |
Optional("jc") | |
Optional("jc") | |
nil | |
--- json.company.name | |
Optional(Netscape) | |
Optional(Netscape) | |
--- json.company.address.zipcode | |
Optional(94043) | |
Optional(94043) | |
Optional(94043.0) | |
nil | |
--- json.company.address.hq | |
Optional(1) | |
Optional(1) | |
Optional(true) | |
Optional(true) | |
Optional(true) | |
--- json.languages | |
Optional("Java") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"username":"jc", | |
"id": 123, | |
"company": { | |
"founded": 1994, | |
"name": "Netscape", | |
"address": { | |
"city": "Mountain View", | |
"zipcode": 94043, | |
"hq": true | |
} | |
}, | |
"languages": [ | |
{"name":"Java", "rank": 8},{"name":"Javascript", "rank": 9}, | |
{"name":"Swift", "rank": 5},{"name":"Python", "rank": 4} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment