JSON.swift 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import Foundation
  2. @dynamicMemberLookup protocol JSON: Codable {
  3. var rawJSON: String { get }
  4. init?(from: String)
  5. }
  6. extension JSON {
  7. var rawJSON: RawJSON {
  8. String(data: try! JSONCoding.encoder.encode(self), encoding: .utf8)!
  9. }
  10. init?(from: String) {
  11. guard let data = from.data(using: .utf8),
  12. let object = try? JSONCoding.decoder.decode(Self.self, from: data)
  13. else {
  14. return nil
  15. }
  16. self = object
  17. }
  18. var dictionaryRepresentation: [String: Any]? {
  19. guard let data = rawJSON.data(using: .utf8),
  20. let dict = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
  21. else {
  22. return nil
  23. }
  24. return dict
  25. }
  26. subscript(dynamicMember string: String) -> Any? {
  27. dictionaryRepresentation?[string]
  28. }
  29. }
  30. extension String: JSON {
  31. var rawJSON: String { self }
  32. init?(from: String) { self = from }
  33. }
  34. extension Double: JSON {}
  35. extension Int: JSON {}
  36. extension Bool: JSON {}
  37. extension Decimal: JSON {}
  38. extension Date: JSON {
  39. init?(from: String) {
  40. let dateFormatter = Formatter.iso8601withFractionalSeconds
  41. let string = from.replacingOccurrences(of: "\"", with: "")
  42. if let date = dateFormatter.date(from: string) {
  43. self = date
  44. } else {
  45. return nil
  46. }
  47. }
  48. }
  49. typealias RawJSON = String
  50. extension RawJSON {
  51. static let null = "null"
  52. static let empty = ""
  53. }
  54. extension Array: JSON where Element: JSON {}
  55. extension Dictionary: JSON where Key: JSON, Value: JSON {}
  56. extension Dictionary where Key == String {
  57. var rawJSON: RawJSON? {
  58. guard let data = try? JSONSerialization.data(withJSONObject: self, options: .prettyPrinted) else { return nil }
  59. return RawJSON(data: data, encoding: .utf8)
  60. }
  61. }
  62. enum JSONCoding {
  63. static var encoder: JSONEncoder {
  64. let encoder = JSONEncoder()
  65. encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes]
  66. encoder.dateEncodingStrategy = .customISO8601
  67. return encoder
  68. }
  69. static var decoder: JSONDecoder {
  70. let decoder = JSONDecoder()
  71. decoder.dateDecodingStrategy = .customISO8601
  72. return decoder
  73. }
  74. }