-
Notifications
You must be signed in to change notification settings - Fork 3
Custom Types
There are 3 main ways (Value, Deserializable and IndexDeserializable) to create a custom type to be used in data extraction.
All the examples will use the following struct:
struct User {
var id: Int
var name: String
var email: String
}This is the main protocol to be used for allowing your custom type to be extracted.
extension User: Value {
static func value(from object: Any) throws -> User {
let id: Int
let name: String
let email: String
// values are in a Dictionary
if let data = object as? Extractable {
id = try data.value(for: "id")
name = try data.value(for: "name")
email = try data.value(for: "email")
}
// values are in an Array
else if let data = object as? IndexExtractable {
id = try data.value(for: 0)
name = try data.value(for: 1)
email = try data.value(for: 2)
}
else {
let expectedType = "Extractable or IndexExtractable"
throw OutlawError.typeMismatch(expected: expectedType, actual: type(of: object))
}
return User(id: id, name: name, email: email)
}
}This protocol was designed to make life easier by supplying an init(object:) initializer instead of creating a static value(from:) method.
extension User: Deserializable {
init(object data: Extractable) throws {
id = try data.value(for: "id")
name = try data.value(for: "name")
email = try data.value(for: "email")
}
}Besides using an initializer, you will notice a few more reductions in the amount of code you have to write. First, you don't need to make sure the data coming into your initializer is a type that you can extract data from. Second, the properties are already typed and so you don't need to specify what the types are of each property.
This protocol is identical to Deserializable except that your data comes from an IndexExtractable object (i.e. Array) instead of an Extractable object (i.e. Dictionary).
extension User: IndexDeserializable {
init(object data: IndexExtractable) throws {
id = try data.value(for: 0)
name = try data.value(for: 1)
email = try data.value(for: 2)
}
}That answer depends on your preference and the structure of your data. Which ever one you decide to pick, you can now extract your custom data type.
If you choose to use Value or Deserializable, you can extract your data like so:
let users: [User] = try json.value(for: "users")If you choose to use Value or IndexDeserializable, you can extract your data like so:
let users: [User] = try json.value(for: 0)