Skip to content

Instantly share code, notes, and snippets.

@rinold
Created December 29, 2017 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rinold/120eefe1e4e5d0f9da5e106120f72216 to your computer and use it in GitHub Desktop.
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
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