JSON.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //
  2. // JSON.swift
  3. // Swifter
  4. //
  5. // Copyright © 2016 Damian Kołakowski. All rights reserved.
  6. //
  7. #if os(Linux)
  8. import Glibc
  9. #else
  10. import Foundation
  11. #endif
  12. // TODO
  13. // - Fix NSNumber extension decoding procedure.
  14. // - Escape key string.
  15. public protocol JsonConvertable {
  16. func asJson(_ ident: UInt?) -> String
  17. }
  18. extension String: JsonConvertable {
  19. public func asJson(_ ident: UInt? = 0) -> String {
  20. return self.unicodeScalars.reduce("\"") { (c, s) -> String in
  21. switch s.value {
  22. case 0 : return c + "\\0"
  23. case 7 : return c + "\\a"
  24. case 8 : return c + "\\b"
  25. case 9 : return c + "\\t"
  26. case 10: return c + "\\n"
  27. case 11: return c + "\\v"
  28. case 12: return c + "\\f"
  29. case 13: return c + "\\r"
  30. case 34: return c + "\\\""
  31. case 39: return c + "\\'"
  32. case 47: return c + "\\/"
  33. case 92: return c + "\\\\"
  34. case let n where n > 127: return c + "\\u" + String(format:"%04X", n)
  35. default:
  36. return c + String(s)
  37. }
  38. } + "\""
  39. }
  40. }
  41. extension Bool: JsonConvertable {
  42. public func asJson(_ ident: UInt?) -> String {
  43. return self ? "true" : "false"
  44. }
  45. }
  46. extension Double: JsonConvertable {
  47. public func asJson(_ ident: UInt?) -> String {
  48. return String(self)
  49. }
  50. }
  51. extension Float: JsonConvertable {
  52. public func asJson(_ ident: UInt?) -> String {
  53. return String(self)
  54. }
  55. }
  56. extension Int: JsonConvertable {
  57. public func asJson(_ ident: UInt?) -> String {
  58. return String(self)
  59. }
  60. }
  61. extension UInt: JsonConvertable {
  62. public func asJson(_ ident: UInt?) -> String {
  63. return String(self)
  64. }
  65. }
  66. extension Int8: JsonConvertable {
  67. public func asJson(_ ident: UInt?) -> String {
  68. return String(self)
  69. }
  70. }
  71. extension UInt8: JsonConvertable {
  72. public func asJson(_ ident: UInt?) -> String {
  73. return String(self)
  74. }
  75. }
  76. extension Int16: JsonConvertable {
  77. public func asJson(_ ident: UInt?) -> String {
  78. return String(self)
  79. }
  80. }
  81. extension UInt16: JsonConvertable {
  82. public func asJson(_ ident: UInt?) -> String {
  83. return String(self)
  84. }
  85. }
  86. extension Int32: JsonConvertable {
  87. public func asJson(_ ident: UInt?) -> String {
  88. return String(self)
  89. }
  90. }
  91. extension UInt32: JsonConvertable {
  92. public func asJson(_ ident: UInt?) -> String {
  93. return String(self)
  94. }
  95. }
  96. extension Int64: JsonConvertable {
  97. public func asJson(_ ident: UInt?) -> String {
  98. return String(self)
  99. }
  100. }
  101. extension UInt64: JsonConvertable {
  102. public func asJson(_ ident: UInt?) -> String {
  103. return String(self)
  104. }
  105. }
  106. extension Dictionary where Key: ExpressibleByStringLiteral, Value: JsonConvertable {
  107. public func asJson(_ ident: UInt?) -> String {
  108. return "{" + self.map({ "\"\($0.0)\":" + $0.1.asJson(ident) }).joined(separator: ",") + "}"
  109. }
  110. }
  111. extension Collection where Iterator.Element: JsonConvertable {
  112. public func asJson(_ ident: UInt?) -> String {
  113. return "[" + (self.map({ $0.asJson(ident) }).joined(separator: ",")) + "]"
  114. }
  115. }
  116. extension Array where Element: JsonConvertable {
  117. public func asJson(_ ident: UInt?) -> String {
  118. return "[" + (self.map({ $0.asJson(ident) }).joined(separator: ",")) + "]"
  119. }
  120. }
  121. extension NSString: JsonConvertable {
  122. public func asJson(_ ident: UInt?) -> String {
  123. return (self as String).asJson(ident)
  124. }
  125. }
  126. extension NSArray: JsonConvertable {
  127. public func asJson(_ ident: UInt?) -> String {
  128. return "[" + (self.map({ ($0 as? JsonConvertable)?.asJson(ident) ?? "null" }).joined(separator: ",")) + "]"
  129. }
  130. }
  131. extension NSNumber: JsonConvertable {
  132. public func asJson(_ ident: UInt?) -> String {
  133. switch String(cString: objCType) {
  134. case "c":
  135. if self == kCFBooleanTrue || self == kCFBooleanFalse {
  136. return self.boolValue.asJson(ident)
  137. }
  138. return self.int8Value.asJson(ident)
  139. case "s": return self.int16Value.asJson(ident)
  140. case "i": return self.int32Value.asJson(ident)
  141. case "q": return self.int64Value.asJson(ident)
  142. case "f": return self.floatValue.asJson(ident)
  143. case "d": return self.doubleValue.asJson(ident)
  144. default:
  145. return self.boolValue.asJson(ident)
  146. }
  147. }
  148. }
  149. extension NSDictionary: JsonConvertable {
  150. public func asJson(_ ident: UInt?) -> String {
  151. return "{" + self.map({ "\"\($0.0)\":" + (($0.1 as? JsonConvertable)?.asJson(ident) ?? "null") }).joined(separator: ",") + "}"
  152. }
  153. }