-
-
Save rwisner/b487583d887d4ed36e3019a4248099cb to your computer and use it in GitHub Desktop.
Swift 3: JSON-serializable structs using protocols
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: # Swift 3: JSON-serializable structs using protocols | |
//: Most of the implementation is based on the code in [this blog post](http://codelle.com/blog/2016/5/an-easy-way-to-convert-swift-structs-to-json/) | |
import Foundation | |
//: ### Defining the protocols | |
protocol JSONRepresentable { | |
var JSONRepresentation: Any { get } | |
} | |
protocol JSONSerializable: JSONRepresentable {} | |
//: ### Implementing the functionality through protocol extensions | |
extension JSONSerializable { | |
var JSONRepresentation: Any { | |
var representation = [String: Any]() | |
for case let (label?, value) in Mirror(reflecting: self).children { | |
switch value { | |
case let value as Dictionary<String, Any>: | |
representation[label] = value as AnyObject | |
case let value as Array<Any>: | |
if let val = value as? [JSONSerializable] { | |
representation[label] = val.map({ $0.JSONRepresentation as AnyObject }) as AnyObject | |
} else { | |
representation[label] = value as AnyObject | |
} | |
case let value: | |
representation[label] = value as AnyObject | |
default: | |
// Ignore any unserializable properties | |
break | |
} | |
} | |
return representation as Any | |
} | |
} | |
extension JSONSerializable { | |
func toJSON() -> String? { | |
let representation = JSONRepresentation | |
guard JSONSerialization.isValidJSONObject(representation) else { | |
print("Invalid JSON Representation") | |
return nil | |
} | |
do { | |
let data = try JSONSerialization.data(withJSONObject: representation, options: []) | |
return String(data: data, encoding: .utf8) | |
} catch { | |
return nil | |
} | |
} | |
} | |
//: ### Define the Structures | |
//: Notice how they are conforming to the `JSONSerializable` protocol | |
struct Author: JSONSerializable { | |
var name: String | |
} | |
struct Book: JSONSerializable { | |
var title: String | |
var isbn: String | |
var pages: Int | |
var authors:[JSONSerializable] | |
var extra:[String: Any] | |
} | |
//: ### Create a sample object for serialization | |
let book = Book( | |
title: "Mirage", | |
isbn: "0399158081", | |
pages: 397, | |
authors: [ | |
Author(name: "Clive Cussler"), | |
Author(name:"Jack Du Brul") | |
], | |
extra: [ | |
"foo": "bar", | |
"baz": 142.226 | |
] | |
) | |
//: ### Use the protocols to convert the data to JSON | |
if let json = book.toJSON() { | |
print(json) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment