Skip to content

Instantly share code, notes, and snippets.

@oisdk
Last active November 23, 2015 12:28
Show Gist options
  • Save oisdk/eaf33e7274891b85fc03 to your computer and use it in GitHub Desktop.
Save oisdk/eaf33e7274891b85fc03 to your computer and use it in GitHub Desktop.
public enum JSON {
case JString(String), JFloat(Double), JInt(Int)
case JArray([JSON]), JObject([String:JSON])
case JBool(Bool), null
}
extension JSON:
IntegerLiteralConvertible,
FloatLiteralConvertible,
BooleanLiteralConvertible,
NilLiteralConvertible,
StringLiteralConvertible,
ArrayLiteralConvertible,
DictionaryLiteralConvertible {
public init(integerLiteral i: Int) { self = .JInt(i) }
public init(floatLiteral f: Double) { self = .JFloat(f) }
public init(booleanLiteral b: Bool) { self = .JBool(b) }
public init(nilLiteral: ()) { self = .null }
public init(stringLiteral s: String) { self = .JString(s) }
public init(extendedGraphemeClusterLiteral s: String) { self = .JString(s) }
public init(unicodeScalarLiteral s: String) { self = .JString(s) }
public init(arrayLiteral a: JSON...) { self = .JArray(a) }
public init(dictionaryLiteral: (String,JSON)...) {
var dict = [String:JSON]()
for (k,v) in dictionaryLiteral { dict[k] = v }
self = .JObject(dict)
}
}
extension JSON: Equatable {}
public func ==(lhs: JSON,rhs:JSON) -> Bool {
switch (lhs, rhs){
case let (.JString(a),.JString(b)): return a == b
case let (.JBool(a) ,.JBool(b) ): return a == b
case let (.JInt(a) ,.JInt(b) ): return a == b
case let (.JFloat(a) ,.JFloat(b) ): return a == b
case let (.JArray(a) ,.JArray(b) ): return a == b
case let (.JObject(a),.JObject(b)): return a == b
case (.null ,.null ): return true
default: return false
}
}
extension JSON {
public var array: [JSON]? {
if case let .JArray(a) = self { return a }
return nil
}
public var object: [String:JSON]? {
if case let .JObject(o) = self { return o }
return nil
}
public var string: String? {
if case let .JString(s) = self { return s }
return nil
}
public var bool: Bool? {
if case let .JBool(b) = self { return b }
return nil
}
public var int: Int? {
if case let .JInt(i) = self { return i }
return nil
}
public var double: Double? {
if case let .JFloat(d) = self { return d }
return nil
}
}
private let ind = " "
extension JSON : CustomStringConvertible {
public var description: String { return indented("") }
private func indented(i: String) -> String {
let lev = i + ind
switch self {
case let .JArray(a) :
let inner = a.lazy.map { e in lev + e.indented(lev) }.joinWithSeparator(",\n")
return "[\n" + inner + "\n" + i + "]"
case let .JObject(o):
let inner = o.lazy.map { (k,v) in lev + k.asJSONString + ": " + v.indented(lev)}
return "{\n" + inner.joinWithSeparator(",\n") + "\n" + i + "}"
case let .JString(s): return s.asJSONString
case let .JBool(b) : return String(b)
case let .JFloat(d) : return String(d)
case let .JInt(i) : return String(i)
case null : return "null"
}
}
}
extension String {
private var asJSONString: String {
return "\"" + String(unicodeScalars.lazy.flatMap { c -> [Character] in
switch c {
case "\\" : return ["\\", "\\"]
case "\"" : return ["\\", "\""]
case "\u{8}" : return ["\\", "b"]
case "\u{12}": return ["\\", "f"]
case "\n" : return ["\\", "n"]
case "\r" : return ["\\", "r"]
case "\t" : return ["\\", "t"]
default : return [Character(c)]
}
}) + "\""
}
}
let jason: JSON = [
"first" : [1, 2, 3],
"sec\"ond": nil,
"third" : "name",
"fourth": [nil, 1, 4.5, false]
]
print(jason)
let x = jason.object?["first"]?.array?[0].int
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment