Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
An Experiment working on Enforced Symmetricality with JohnSundell's Wrap+Unbox
// A definition for the kind of model objects this library can work on
import Foundation
public protocol CollieModel: Unboxable, WrapCustomizable, Hashable, CustomStringConvertible {
/// Configure the mapping between client and server property names. keys are client names and values are JSON names eg: "authorId: "author_id"
static var propertyMapping: [String: String]? { get }
extension CollieModel {
/// Default property mapping is nil (I'd do an optional get-only var protocol requirement but the language doesn't allow it)
static var propertyMapping: [String:String]? { return nil }
This is the default implementation of value equality for models.
If you have a faster way to do value comparison for your model type feel free to override it.
- parameter otherModel: Another homogenous model to compare to
- returns: true if every property is the same between both models
func sameValueAs<T: CollieModel>(otherModel: T) -> Bool {
do {
let a: Collie.JSON = try Wrap(self)
let b: Collie.JSON = try Wrap(otherModel)
let same = NSDictionary(dictionary: a).isEqualToDictionary(b)
if !same { Collie.trace("!sameValueAs() \n\(a) \n\(b)") }
return same
} catch {
print("sameValueAs error: \(error)")
return false
Check to see if this object is symmetrical--you can turn it into JSON and back, and all the values match
- returns: true if all the values match
func isSymmetrical() -> Bool {
guard let json = self.toJSON() else { return false }
guard let other = Self(json: json, skipSymmetryValidation: true) else { return false }
let isSymmetrical = self.sameValueAs(other)
Collie.trace("[\(json["id"] ?? "")].isSymmetrical()? \(isSymmetrical)")
return isSymmetrical
func toJSON() -> Collie.JSON? {
do {
let json: Collie.JSON = try Wrap(self)
return json
} catch {
print("toJSON() error: \(error)")
return nil
init?(json: Collie.JSON, skipSymmetryValidation: Bool = false) {
do {
self = try Unbox(json)
if !skipSymmetryValidation { self.isSymmetrical() }
} catch {
print("init?(json:) error: \(error)")
return nil
static func getKey(key: String) -> String { return Self.propertyMapping?[key] ?? key }
func keyForWrappingPropertyNamed(propertyName: String) -> String? {
return Self.getKey(propertyName)
// An Example model
class GooglePlace: CollieModel {
let id: String
let name: String
let rating: Double
let thumbnailUrl: String
static let propertyMapping: [String : String]? = [
"id": "place_id",
"thumbnailUrl": "icon",
required init(unboxer: Unboxer) {
id = unboxer.unbox( GooglePlace.getKey("id") )
name = unboxer.unbox( GooglePlace.getKey("name") )
rating = unboxer.unbox( GooglePlace.getKey("rating") )
thumbnailUrl = unboxer.unbox( GooglePlace.getKey("thumbnailUrl") )

This comment has been minimized.

Copy link
Owner Author

SimplGy commented May 17, 2016

Revision 4 now has symmetry enforced for simple property renaming cases. I'd still like to slim down that required init boilerplate though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.