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
class Pet: Codable { | |
let name: String | |
} | |
class Cat: Pet { | |
var lives: Int | |
} | |
class Dog: Pet { | |
func fetch() { /**/ } | |
} |
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
{ | |
"name": "Kewin", | |
"pets": [ | |
{ | |
"type": "Cat", | |
"name": "Garfield", | |
"lives": 9 | |
}, | |
{ | |
"type": "Dog", |
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
class Person: Codable { | |
let name: String | |
/// Retrieve the pets of the Person. | |
func getPets(completion: ([Pet]) -> Void) throws { | |
// Networking request omitted for simplicity. | |
let data = responseData | |
completion(try JSONDecoder().decode([Pet].self, from: data)) | |
} | |
} |
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
/// To support a new class family, create an enum that conforms to this protocol and contains the different types. | |
protocol ClassFamily: Decodable { | |
/// The discriminator key. | |
static var discriminator: Discriminator { get } | |
/// Returns the class type of the object coresponding to the value. | |
func getType() -> AnyObject.Type | |
} | |
/// Discriminator key enum used to retrieve discriminator fields in JSON payloads. |
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
/// The PetFamily enum describes the Pet family of objects. | |
enum PetFamily: String, ClassFamily { | |
case cat = "Cat" | |
case dog = "Dog" | |
static var discriminator: Discriminator = .type | |
func getType() -> AnyObject.Type { | |
switch self { | |
case .cat: |
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
class ClassWrapper<T: ClassFamily, U: Decodable>: Decodable { | |
/// The family enum containing the class information. | |
let family: T | |
// The decoded object. Can be any subclass of U. | |
let object: U? | |
required init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: Discriminator.self) | |
// Decode the family with the discriminator. | |
family = try container.decode(T.self, forKey: T.discriminator) |
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
class Person: Codable { | |
let name: String | |
/// Retrieve the pets of the Person. | |
func getPets(completion: ([Pet]) -> Void) throws { | |
// Networking request omitted for simplicity. | |
let data = responseData | |
completion(try JSONDecoder().decode([ClassWrapper<PetFamily, Pet>].self, from: data).compactMap { $0.object }) | |
} |
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
extension JSONDecoder { | |
/// Decode a heterogeneous list of objects. | |
/// - Parameters: | |
/// - family: The ClassFamily enum type to decode with. | |
/// - data: The data to decode. | |
/// - Returns: The list of decoded objects. | |
func decode<T: ClassFamily, U: Decodable>(family: T.Type, from data: Data) throws -> [U] { | |
return try self.decode([ClassWrapper<T, U>].self, from: data).compactMap { $0.object } | |
} | |
} |
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
/// Retrieve the pets of the Person. | |
func getPets(completion: ([Pet]) -> Void) throws { | |
// Networking request omitted for simplicity. | |
if let data = responseData { | |
completion(try JSONDecoder().decode(family: PetFamily.self, from: data)) | |
} | |
} |
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
import Foundation | |
// MARK: - Model classes | |
/// The Pet superclass. | |
class Pet: Codable { | |
/// The name of the pet. | |
let name: String | |
enum CodingKeys: String, CodingKey { | |
case name |
OlderNewer