Skip to content

Instantly share code, notes, and snippets.

@jparishy
Created December 28, 2015 19:58
Show Gist options
  • Save jparishy/ea791c2b21ab040c0053 to your computer and use it in GitHub Desktop.
Save jparishy/ea791c2b21ab040c0053 to your computer and use it in GitHub Desktop.
//
// _JSONWriting.swift
// Swerver
//
// Created by Julius Parishy on 12/13/15.
// Copyright © 2015 Julius Parishy. All rights reserved.
//
import Foundation
extension NSJSONSerialization {
public class func _impl_swerver_dataWithJSONObject(obj: [JSONEncodable], options opt: NSJSONWritingOptions) throws -> NSData {
let prettyPrinted = ((opt.rawValue | NSJSONWritingOptions.PrettyPrinted.rawValue) == 0)
let output = try obj.JSONString(prettyPrinted, indentationLevel: 0)
let bytes = output.bridge().swerver_cStringUsingEncoding(NSUTF8StringEncoding)
return NSData(bytes: bytes, length: bytes.count)
}
public class func _impl_swerver_dataWithJSONObject(obj: [String:JSONEncodable], options opt: NSJSONWritingOptions) throws -> NSData {
let prettyPrinted = ((opt.rawValue | NSJSONWritingOptions.PrettyPrinted.rawValue) == 0)
let output = try obj.JSONString(prettyPrinted, indentationLevel: 0)
let bytes = output.bridge().swerver_cStringUsingEncoding(NSUTF8StringEncoding)
return NSData(bytes: bytes, length: bytes.count)
}
public class func _impl_swerver_dataWithJSONObject<T : JSONEncodable>(obj: [T], options opt: NSJSONWritingOptions) throws -> NSData {
let validObj = obj.map {
v in
return v as JSONEncodable
}
return try _impl_swerver_dataWithJSONObject(validObj, options: opt)
}
public class func _impl_swerver_dataWithJSONObject<T : JSONEncodable>(obj: [String:T], options opt: NSJSONWritingOptions) throws -> NSData {
let validObj = mapDict(obj) {
(k: String, v: T) -> (String, JSONEncodable) in
return (k, v as JSONEncodable)
}
return try _impl_swerver_dataWithJSONObject(validObj, options: opt)
}
}
private func mapDict<K : Hashable, V, OK : Hashable, OV>(dict: Dictionary<K,V>, f: ((K,V) -> (OK,OV))) -> Dictionary<OK, OV> {
var out = Dictionary<OK, OV>()
for (k,v) in dict {
let (ok,ov) = f(k, v)
out[ok] = ov
}
return out
}
private func Indentation(level: Int) -> String {
return String(count: level, repeatedValue: Character("\t"))
}
extension JSONEncodable {
private func JSONString(prettyPrinted: Bool, indentationLevel: Int) throws -> String {
if let s = self as? String {
return try s.JSONString(prettyPrinted)
} else if let s = self as? Int {
return try s.JSONString(prettyPrinted)
} else if let s = self as? Double {
return try s.JSONString(prettyPrinted)
} else if let s = self as? Float {
return try s.JSONString(prettyPrinted)
} else if let s = self as? Bool {
return try s.JSONString(prettyPrinted)
} else if let s = self as? NSNull {
return try s.JSONString(prettyPrinted)
} else if let s = self as? Dictionary<String, JSONEncodable> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Dictionary<String, Int> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Dictionary<String, Double> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Dictionary<String, Float> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Dictionary<String, Bool> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Dictionary<String, String> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Dictionary<String, NSNull> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<Int> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<Double> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<Float> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<Bool> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<String> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<NSNull> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else if let s = self as? Array<JSONEncodable> {
return try s.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else {
throw JSONError.InvalidInput
}
}
}
extension Dictionary {
private func JSONString(prettyPrinted: Bool, indentationLevel: Int) throws -> String {
var output = ""
if prettyPrinted {
output += Indentation(indentationLevel)
}
output += "{"
if prettyPrinted {
output += "\n"
}
var index = 0
let keys: [Key] = Array(self.keys).sort { (k1: Key, k2: Key) -> Bool in
if let s1 = k1 as? String, s2 = k2 as? String {
return s1 < s2
} else {
return false
}
}
for k in keys {
let v = self[k]
if let k = k as? String, v = v as? JSONEncodable {
if prettyPrinted {
output += Indentation(indentationLevel + 1)
}
output += try k.JSONString(prettyPrinted)
output += ":"
if prettyPrinted {
output += " "
}
output += try v.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else {
throw JSONError.InvalidInput
}
if index < self.count - 1 {
output += ","
if prettyPrinted {
output += "\n"
}
}
index += 1
}
if prettyPrinted {
output += "\n"
output += Indentation(indentationLevel)
}
output += "}"
return output
}
}
extension Array {
private func JSONString(prettyPrinted: Bool, indentationLevel: Int) throws -> String {
var output = ""
if prettyPrinted {
output += Indentation(indentationLevel)
}
output += "["
if prettyPrinted {
output += "\n"
}
var index = 0
for v in self {
if let v = v as? JSONEncodable {
output += try v.JSONString(prettyPrinted, indentationLevel: indentationLevel)
} else {
throw JSONError.InvalidInput
}
if index < self.count - 1 {
output += ","
if prettyPrinted {
output += "\n"
}
}
index += 1
}
if prettyPrinted {
output += "\n"
output += Indentation(indentationLevel)
}
output += "]"
return output
}
}
extension String {
private func JSONString(prettyPrinted: Bool) throws -> String {
return "\"\(self)\""
}
}
extension Int {
private func JSONString(prettyPrinted: Bool) throws -> String {
return "\(self)"
}
}
extension Double {
private func JSONString(prettyPrinted: Bool) throws -> String {
return "\(self)"
}
}
extension Float {
private func JSONString(prettyPrinted: Bool) throws -> String {
return "\(self)"
}
}
extension Bool {
private func JSONString(prettyPrinted: Bool) throws -> String {
return self ? "true" : "false"
}
}
extension NSNull {
private func JSONString(prettyPrinted: Bool) throws -> String {
return "null"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment