public enum JSON: ArrayLiteralConvertible, BooleanLiteralConvertible, DictionaryLiteralConvertible, Equatable, FloatLiteralConvertible, IntegerLiteralConvertible, JSONConvertible, NilLiteralConvertible, StringLiteralConvertible { public typealias ArrayType = [Doubt.JSON] public typealias DictionaryType = [Swift.String:Doubt.JSON] case Number(Double) case Boolean(Bool) case String(Swift.String) case Array(ArrayType) case Dictionary(DictionaryType) case Null public init(_ convertible: CustomJSONConvertible) { self = convertible.JSON } public var number: Double? { if case let .Number(d) = self { return d } return nil } public var boolean: Bool? { if case let .Boolean(b) = self { return b } return nil } public var string: Swift.String? { if case let .String(s) = self { return s } return nil } public var array: ArrayType? { if case let .Array(a) = self { return a } return nil } public var dictionary: DictionaryType? { if case let .Dictionary(d) = self { return d } return nil } public var isNull: Bool { if case .Null = self { return true } return false } public init?(object: AnyObject) { struct E: ErrorType {} func die() throws -> T { throw E() } do { switch object { case let n as Double: self = .Number(n) case let b as Bool: self = .Boolean(b) case let s as Swift.String: self = .String(s) case let a as [AnyObject]: self = .Array(try a.map { try Doubt.JSON(object: $0) ?? die() }) case let d as [Swift.String:AnyObject]: self = .Dictionary(Swift.Dictionary(elements: try d.map { ($0, try Doubt.JSON(object: $1) ?? die()) })) case is NSNull: self = .Null default: return nil } } catch { return nil } } public var object: AnyObject { switch self { case let .Number(n): return n case let .Boolean(b): return b case let .String(s): return s case let .Array(a): return a.map { $0.object } case let .Dictionary(d): return Swift.Dictionary(elements: d.map { ($0, $1.object) }) case .Null: return NSNull() } } public func serialize() -> NSData { return try! NSJSONSerialization.dataWithJSONObject(object, options: []) } // MARK: ArrayLiteralConvertible public init(arrayLiteral: Doubt.JSON...) { self = .Array(arrayLiteral) } // MARK: BooleanLiteralConvertible public init(booleanLiteral: Bool) { self = .Boolean(booleanLiteral) } // MARK: DictionaryLiteralConvertible public init(dictionaryLiteral: (Swift.String, Doubt.JSON)...) { self = .Dictionary(Swift.Dictionary(elements: dictionaryLiteral)) } // MARK: FloatLiteralConvertible public init(floatLiteral: Double) { self = .Number(floatLiteral) } // MARK: IntegerLiteralConvertible public init(integerLiteral: Int) { self = .Number(Double(integerLiteral)) } // MARK: JSONConvertible public init?(JSON: Doubt.JSON) { self = JSON } public var JSON: Doubt.JSON { return self } // MARK: NilLiteralConvertible public init(nilLiteral: ()) { self = .Null } // MARK: StringLiteralConvertible public init(stringLiteral: Swift.String) { self = .String(stringLiteral) } } public func == (left: JSON, right: JSON) -> Bool { switch (left, right) { case let (.Number(a), .Number(b)): return a == b case let (.Boolean(a), .Boolean(b)): return a == b case let (.String(a), .String(b)): return a == b case let (.Array(a), .Array(b)): return a == b case let (.Dictionary(a), .Dictionary(b)): return a == b case (.Null, .Null): return true default: return false } } /// A type which can be converted to JSON. public protocol CustomJSONConvertible { var JSON: Doubt.JSON { get } } extension String: CustomJSONConvertible { public var JSON: Doubt.JSON { return .String(self) } } extension Int: CustomJSONConvertible { public var JSON: Doubt.JSON { return .Number(Double(self)) } } extension Array where Element: CustomJSONConvertible { public var JSON: Doubt.JSON { return .Array(map { Doubt.JSON($0) }) } } extension Range where Element: CustomJSONConvertible, Element.Distance: CustomJSONConvertible { public var JSON: Doubt.JSON { return [ startIndex.JSON, count.JSON, ] } } /// A type which can be converted to and from JSON. public protocol JSONConvertible: CustomJSONConvertible { init?(JSON: Doubt.JSON) } import Foundation