Created
January 1, 2015 13:07
-
-
Save akisute/e2d523b821ca0fad46e2 to your computer and use it in GitHub Desktop.
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 | |
public class JSON { | |
private let _value:AnyObject | |
public init(_ obj:AnyObject) { self._value = obj } | |
public init(_ json:JSON){ self._value = json._value } | |
} | |
extension JSON { | |
public typealias NSNull = Foundation.NSNull | |
public typealias NSError = Foundation.NSError | |
public class var null:NSNull { return NSNull() } | |
public convenience init(data:NSData) { | |
var err:NSError? | |
var obj:AnyObject? = NSJSONSerialization.JSONObjectWithData( | |
data, options:nil, error:&err | |
) | |
self.init(err != nil ? err! : obj!) | |
} | |
public convenience init(string:String) { | |
let enc:NSStringEncoding = NSUTF8StringEncoding | |
self.init(data: string.dataUsingEncoding(enc)!) | |
} | |
public class func parse(string:String)->JSON { | |
return JSON(string:string) | |
} | |
public convenience init(nsurl:NSURL) { | |
var enc:NSStringEncoding = NSUTF8StringEncoding | |
var err:NSError? | |
let str:String? = | |
NSString( | |
contentsOfURL:nsurl, usedEncoding:&enc, error:&err | |
) | |
if err != nil { self.init(err!) } | |
else { self.init(string:str!) } | |
} | |
public class func fromNSURL(nsurl:NSURL) -> JSON { | |
return JSON(nsurl:nsurl) | |
} | |
public convenience init(url:String) { | |
if let nsurl = NSURL(string:url) as NSURL? { | |
self.init(nsurl:nsurl) | |
} else { | |
self.init(NSError( | |
domain:"JSONErrorDomain", | |
code:400, | |
userInfo:[NSLocalizedDescriptionKey: "malformed URL"] | |
) | |
) | |
} | |
} | |
public class func fromURL(url:String) -> JSON { | |
return JSON(url:url) | |
} | |
public class func stringify(obj:AnyObject, pretty:Bool=false) -> String! { | |
if !NSJSONSerialization.isValidJSONObject(obj) { | |
JSON(NSError( | |
domain:"JSONErrorDomain", | |
code:422, | |
userInfo:[NSLocalizedDescriptionKey: "not an JSON object"] | |
)) | |
return nil | |
} | |
return JSON(obj).toString(pretty:pretty) | |
} | |
} | |
extension JSON { | |
public subscript(idx:Int) -> JSON { | |
switch _value { | |
case let err as NSError: | |
return self | |
case let ary as NSArray: | |
if 0 <= idx && idx < ary.count { | |
return JSON(ary[idx]) | |
} | |
return JSON(NSError( | |
domain:"JSONErrorDomain", code:404, userInfo:[ | |
NSLocalizedDescriptionKey: | |
"[\(idx)] is out of range" | |
])) | |
default: | |
return JSON(NSError( | |
domain:"JSONErrorDomain", code:500, userInfo:[ | |
NSLocalizedDescriptionKey: "not an array" | |
])) | |
} | |
} | |
public subscript(key:String)->JSON { | |
switch _value { | |
case let err as NSError: | |
return self | |
case let dic as NSDictionary: | |
if let val:AnyObject = dic[key] { return JSON(val) } | |
return JSON(NSError( | |
domain:"JSONErrorDomain", code:404, userInfo:[ | |
NSLocalizedDescriptionKey: | |
"[\"\(key)\"] not found" | |
])) | |
default: | |
return JSON(NSError( | |
domain:"JSONErrorDomain", code:500, userInfo:[ | |
NSLocalizedDescriptionKey: "not an object" | |
])) | |
} | |
} | |
public var data:AnyObject? { | |
return self.isError ? nil : self._value | |
} | |
public var type:String { | |
switch _value { | |
case is NSError: return "NSError" | |
case is NSNull: return "NSNull" | |
case let o as NSNumber: | |
switch String.fromCString(o.objCType)! { | |
case "c", "C": return "Bool" | |
case "q", "l", "i", "s": return "Int" | |
case "Q", "L", "I", "S": return "UInt" | |
default: return "Double" | |
} | |
case is NSString: return "String" | |
case is NSArray: return "Array" | |
case is NSDictionary: return "Dictionary" | |
default: return "NSError" | |
} | |
} | |
public var isError: Bool { return _value is NSError } | |
public var isNull: Bool { return _value is NSNull } | |
public var isBool: Bool { return type == "Bool" } | |
public var isInt: Bool { return type == "Int" } | |
public var isUInt: Bool { return type == "UInt" } | |
public var isDouble: Bool { return type == "Double" } | |
public var isNumber: Bool { | |
if let o = _value as? NSNumber { | |
let t = String.fromCString(o.objCType)! | |
return t != "c" && t != "C" | |
} | |
return false | |
} | |
public var isString: Bool { return _value is NSString } | |
public var isArray: Bool { return _value is NSArray } | |
public var isDictionary: Bool { return _value is NSDictionary } | |
public var isLeaf: Bool { | |
return !(isArray || isDictionary || isError) | |
} | |
public var asError:NSError? { | |
return _value as? NSError | |
} | |
public var asNull:NSNull? { | |
return _value is NSNull ? JSON.null : nil | |
} | |
public var asBool:Bool? { | |
switch _value { | |
case let o as NSNumber: | |
switch String.fromCString(o.objCType)! { | |
case "c", "C": return Bool(o.boolValue) | |
default: | |
return nil | |
} | |
default: return nil | |
} | |
} | |
public var asInt:Int? { | |
switch _value { | |
case let o as NSNumber: | |
switch String.fromCString(o.objCType)! { | |
case "c", "C": | |
return nil | |
default: | |
return Int(o.longLongValue) | |
} | |
default: return nil | |
} | |
} | |
public var asDouble:Double? { | |
switch _value { | |
case let o as NSNumber: | |
switch String.fromCString(o.objCType)! { | |
case "c", "C": | |
return nil | |
default: | |
return Double(o.doubleValue) | |
} | |
default: return nil | |
} | |
} | |
public var asNumber:Double? { return asDouble } | |
public var asString:String? { | |
switch _value { | |
case let o as NSString: | |
return o as String | |
default: return nil | |
} | |
} | |
public var asArray:[JSON]? { | |
switch _value { | |
case let o as NSArray: | |
var result = [JSON]() | |
for v:AnyObject in o { result.append(JSON(v)) } | |
return result | |
default: | |
return nil | |
} | |
} | |
public var asDictionary:[String:JSON]? { | |
switch _value { | |
case let o as NSDictionary: | |
var result = [String:JSON]() | |
for (k:AnyObject, v:AnyObject) in o { | |
result[k as String] = JSON(v) | |
} | |
return result | |
default: return nil | |
} | |
} | |
public var asDate:NSDate? { | |
if let dateString = _value as? NSString { | |
let dateFormatter = NSDateFormatter() | |
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ" | |
return dateFormatter.dateFromString(dateString) | |
} | |
return nil | |
} | |
public var length:Int { | |
switch _value { | |
case let o as NSArray: return o.count | |
case let o as NSDictionary: return o.count | |
default: return 0 | |
} | |
} | |
} | |
extension JSON : SequenceType { | |
public func generate()->GeneratorOf<(AnyObject,JSON)> { | |
switch _value { | |
case let o as NSArray: | |
var i = -1 | |
return GeneratorOf<(AnyObject, JSON)> { | |
if ++i == o.count { return nil } | |
return (i, JSON(o[i])) | |
} | |
case let o as NSDictionary: | |
var ks = o.allKeys.reverse() | |
return GeneratorOf<(AnyObject, JSON)> { | |
if ks.isEmpty { return nil } | |
let k = ks.removeLast() as String | |
return (k, JSON(o.valueForKey(k)!)) | |
} | |
default: | |
return GeneratorOf<(AnyObject, JSON)>{ nil } | |
} | |
} | |
public func mutableCopyOfTheObject() -> AnyObject { | |
return _value.mutableCopy() | |
} | |
} | |
extension JSON : Printable { | |
public func toString(pretty:Bool=false)->String { | |
switch _value { | |
case is NSError: return "\(_value)" | |
case is NSNull: return "null" | |
case let o as NSNumber: | |
switch String.fromCString(o.objCType)! { | |
case "c", "C": | |
return o.boolValue.description | |
case "q", "l", "i", "s": | |
return o.longLongValue.description | |
case "Q", "L", "I", "S": | |
return o.unsignedLongLongValue.description | |
default: | |
switch o.doubleValue { | |
case 0.0/0.0: return "0.0/0.0" | |
case -1.0/0.0: return "-1.0/0.0" | |
case +1.0/0.0: return "+1.0/0.0" | |
default: | |
return o.doubleValue.description | |
} | |
} | |
case let o as NSString: | |
return o.debugDescription | |
default: | |
let opts = pretty | |
? NSJSONWritingOptions.PrettyPrinted : nil | |
if let data = NSJSONSerialization.dataWithJSONObject( | |
_value, options:opts, error:nil | |
) as NSData? { | |
if let nsstring = NSString( | |
data:data, encoding:NSUTF8StringEncoding | |
) as NSString? { | |
return nsstring | |
} | |
} | |
return "YOU ARE NOT SUPPOSED TO SEE THIS!" | |
} | |
} | |
public var description:String { return toString() } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment