Skip to content

Instantly share code, notes, and snippets.

@aryaxt
Last active November 4, 2016 19:15
Show Gist options
  • Save aryaxt/339547363e5caae9dcd9ef6b67a55724 to your computer and use it in GitHub Desktop.
Save aryaxt/339547363e5caae9dcd9ef6b67a55724 to your computer and use it in GitHub Desktop.
Swift auto object serialization
public protocol Serializable {
func serialize() -> [String: Any]
}
extension Serializable {
public func serialize() -> [String: Any] {
return Self.makeSerialized(serializable: self)
}
public static func makeSerialized(serializable: Self) -> [String: Any] {
return serializeSerializable(serializable)
}
}
fileprivate func serializeSerializable(_ serializable: Serializable) -> [String: Any] {
var result = [String: Any]()
var enumeratingMirror: Mirror? = Mirror(reflecting: serializable)
while true {
guard let mirror = enumeratingMirror else { break }
for child in mirror.children {
if let label = child.label, let dictionaryValue = getDictionaryValue(child.value) {
result[label] = dictionaryValue
}
}
enumeratingMirror = mirror.superclassMirror
}
return result
}
fileprivate func getDictionaryValue(_ any: Any) -> Any? {
let unwrappedValue: Any
if isOptional(any) {
switch any {
case let optional as Optional<Any>:
if case .some(let insideOptional) = optional {
unwrappedValue = insideOptional
}
else {
return nil
}
}
}
else {
unwrappedValue = any
}
switch unwrappedValue {
case let serializable as Serializable:
return serializeSerializable(serializable)
case let serializableList as [Serializable]:
return serializableList.map { serializeSerializable($0) }
case let rawRepresentable as RawRepresentable:
return rawRepresentable.getValueAsAny()
default:
return unwrappedValue
}
}
private func isOptional<T>(_ input: T) -> Bool {
let mirror = Mirror(reflecting: input)
let style = mirror.displayStyle
switch style {
case .some(.optional):
return true
default:
return false
}
}
extension Collection where Iterator.Element: Serializable {
public func serialize() -> [[String: Any]] {
return map { $0.serialize() }
}
}
extension RawRepresentable {
public func getValueAsAny() -> Any {
return rawValue
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment