Skip to content

Instantly share code, notes, and snippets.

@nathantannar4
Created December 17, 2018 22:17
Show Gist options
  • Save nathantannar4/97fc656889c4669bfb179b54bf88f24c to your computer and use it in GitHub Desktop.
Save nathantannar4/97fc656889c4669bfb179b54bf88f24c to your computer and use it in GitHub Desktop.
Generate JSON representation of values using the Mirror API
//
// Reflectable.swift
//
// Created by Nathan Tannar on 2018-12-04.
//
import Foundation
// Add this protocol to your `struct` or `class`
protocol Reflectable {
func asJSON() -> Any?
}
// A RawValue `enum` can be reflected if it conforms to
protocol RawValueReflectable: Reflectable {}
extension Reflectable {
func asJSON() -> Any? {
let mirror = Mirror(reflecting: self)
guard mirror.children.count > 0 else { return self }
var out: [String: Any] = [:]
for case let (key?, value) in mirror.children {
if let value = value as? Reflectable {
out[key] = value.asJSON()
}
}
return out
}
}
extension String: Reflectable {}
extension Int: Reflectable {}
extension Float: Reflectable {}
extension Double: Reflectable {}
extension Bool: Reflectable {}
extension Array: Reflectable where Element: Reflectable {
func asJSON() -> Any? {
return compactMap { $0.asJSON() }
}
}
extension Optional: Reflectable where Wrapped: Reflectable {
func asJSON() -> Any? {
switch self {
case .some(let value):
return value.asJSON()
case .none:
return nil
}
}
}
extension Dictionary: Reflectable where Key == String, Value: Reflectable {
func asJSON() -> Any? {
return mapValues { $0.asJSON() ?? $0 }
}
}
extension RawValueReflectable where Self: RawRepresentable, Self.RawValue: Reflectable {
func asJSON() -> Any? {
return rawValue
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment