Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save V8tr/3ab9ab1a550415fae5d61aa39d3a2185 to your computer and use it in GitHub Desktop.
Save V8tr/3ab9ab1a550415fae5d61aa39d3a2185 to your computer and use it in GitHub Desktop.
Sample code for my blog post Reflection and Mirror in Swift http://www.vadimbulavin.com/2018-03-09-reflection-and-mirror-in-swift/
import Foundation
protocol JSONSerializable {
func toJSON() throws -> Any?
}
enum CouldNotSerializeError: Error {
case noImplementation(source: Any, type: String)
case undefinedKey(source: Any, type: String)
}
extension JSONSerializable {
func toJSON() throws -> Any? {
let mirror = Mirror(reflecting: self)
guard !mirror.children.isEmpty else { return self }
var result: [String: Any] = [:]
for child in mirror.children {
if let value = child.value as? JSONSerializable {
if let key = child.label {
result[key] = try value.toJSON()
} else {
throw CouldNotSerializeError.undefinedKey(source: self, type: String(describing: type(of: child.value)))
}
} else {
throw CouldNotSerializeError.noImplementation(source: self, type: String(describing: type(of: child.value)))
}
}
return result
}
}
struct Order {
let uid = UUID()
let itemsCount = 1
let isDeleted = false
let name = "A cup"
let subtitle: String? = nil
let category = Category(name: "Cups")
}
struct Category {
let name: String
}
extension String: JSONSerializable {}
extension Int: JSONSerializable {}
extension Bool: JSONSerializable {}
extension UUID: JSONSerializable {}
extension Order: JSONSerializable {}
extension Category: JSONSerializable {}
extension Optional: JSONSerializable {
func toJSON() throws -> Any? {
if let x = self {
guard let value = x as? JSONSerializable else {
throw CouldNotSerializeError.noImplementation(source: x, type: String(describing: type(of: x)))
}
return try value.toJSON()
}
return nil
}
}
do {
try Order().toJSON()
} catch {
print(error)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment