Created
December 29, 2017 15:35
-
-
Save rinold/120eefe1e4e5d0f9da5e106120f72216 to your computer and use it in GitHub Desktop.
swift-4-how-to-implement-codable-protocol-for-json-array-of-different-types
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 | |
let dataString = "{ \"materials\": [ { \"reflection\": { \"title\": \"3-2-1 reflection\", \"description\": \"please reflect after today\", \"questions\": [ { \"question\": \"question 1\", \"answer\": \"answer 1\", \"answerImageUrl\": \"http://xxx\" }, { \"question\": \"question 1\", \"answer\": \"answer 1\", \"answerImageUrl\": \"http://xxx\" } ] } }, { \"video\": { \"title\": \"the jungle\", \"description\": \"please watch after today lesson\", \"videoUrl\": \"http://\" } }, { \"note\": { \"title\": \"the note\", \"description\": \"please read after today lesson\" } } ]}" | |
let data = dataString.data(using: .utf8)! | |
struct Response: Codable { | |
let materials: [Material] | |
} | |
enum Material: Codable { | |
case video(Video) | |
case reflection(Reflection) | |
case note(Note) | |
enum CodingKeys: String, CodingKey { | |
case video | |
case reflection | |
case note | |
} | |
struct UnknownMaterialError: Error {} | |
init(from decoder: Decoder) throws { | |
let values = try decoder.container(keyedBy: CodingKeys.self) | |
if let video = try? values.decode(Video.self, forKey: CodingKeys.video) { | |
self = .video(video) | |
} else if let reflection = try? values.decode(Reflection.self, forKey: CodingKeys.reflection) { | |
self = .reflection(reflection) | |
} else if let note = try? values.decode(Note.self, forKey: CodingKeys.note) { | |
self = .note(note) | |
} else { | |
throw UnknownMaterialError() | |
} | |
} | |
func encode(to encoder: Encoder) throws -> () { | |
switch self { | |
case .video(let video): | |
try video.encode(to: encoder) | |
case .reflection(let reflection): | |
try reflection.encode(to: encoder) | |
case .note(let note): | |
try note.encode(to: encoder) | |
} | |
} | |
} | |
struct Video: Codable { | |
let title, description, videoUrl: String | |
} | |
struct Reflection: Codable { | |
let title, description: String | |
let questions: [Question] | |
} | |
struct Question: Codable { | |
let question, answer, answerImageUrl: String | |
} | |
struct Note: Codable { | |
let title, description: String | |
} | |
let response = try JSONDecoder().decode(Response.self, from: data) | |
print (response) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment