-
-
Save iKova47/10bab5ba3db5c1314d4ff4b68008fcce to your computer and use it in GitHub Desktop.
Make a Swift Array conform to Decodable (for JSON parsing)
This file contains hidden or 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
| /* | |
| * | |
| * An extension for array that takes JSON as a parameter and tries to parse all elements form the given | |
| * JSON to the Decodable.Type model. Also, in case that the given JSON is not an array type, it will try | |
| * to parse single model and append it to the self. | |
| * | |
| * Useful in situations where JSON sometimes can be object and some other times array, e.g. when converting from XML to JSON. | |
| * | |
| * This extension uses SwiftyJSON as JSON parsing engine, but it can be made to work with other libraries or manual parsing from Dictionary json. | |
| */ | |
| import SwiftyJSON | |
| public protocol Decodable { | |
| init?(json: JSON) | |
| } | |
| extension Array: Decodable { | |
| public init?(json: JSON) { | |
| // return early if the json is not valid or Elenent does not confirm to the Decodable protocol | |
| guard json.exists(), Element.self is Decodable.Type else { | |
| return nil | |
| } | |
| if let decodableType = Element.self as? Decodable.Type { | |
| // try to get array from this json | |
| if let arrayJSON = json.array { | |
| let elements = arrayJSON.flatMap({ decodableType.init(json: $0) as? Element }) | |
| self.init() | |
| self.append(contentsOf: elements) | |
| } else { | |
| // try to get element from json (in case the response contains object instead of the array) | |
| guard let element = decodableType.init(json: json) as? Element else { | |
| return nil | |
| } | |
| self.init() | |
| self.append(element) | |
| } | |
| } else { | |
| return nil | |
| } | |
| } | |
| } | |
| // MARK: Usage | |
| struct User: Decodable { | |
| let name: String | |
| let surname: String | |
| init?(json: JSON) { | |
| guard let name = json["name"].string, let surname = json["surname"].string else { | |
| return nil | |
| } | |
| self.name = name | |
| self.surname = surname | |
| } | |
| } | |
| //Let's say you got a JSON array of User objects | |
| let usersJSON: JSON | |
| let users = [User](json: usersJSON) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment