Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Foundation
- /// Simple example of decoding different values based on a "type" field
- let json = Data("""
- [{
- "type": "user",
- "name": "Alice"
- },
- {
- "type": "document",
- "path": "/etc/passwd"
- }
- ]
- """.utf8)
- struct User: Codable {
- let name: String
- }
- struct Document: Codable {
- let path: String
- }
- enum Item {
- case user(User)
- case document(Document)
- }
- extension Item: Codable {
- enum CodingKeys: CodingKey {
- case type
- }
- init(from decoder: Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
- let type = try container.decode(String.self, forKey: .type)
- // The important point here is that you can extract a second container with a different
- // CodingKey from the same decoder.
- switch type {
- case "user": self = .user(try User(from: decoder))
- case "document": self = .document(try Document(from: decoder))
- default: throw DecodingError.dataCorruptedError(forKey: .type, in: container,
- debugDescription: "Unknown type")
- }
- }
- func encode(to encoder: Encoder) throws {
- var container = encoder.container(keyedBy: CodingKeys.self)
- switch self {
- case .user(let user):
- // And similarly, you can just keep encoding other stuff into the current encoder.
- try container.encode("user", forKey: .type)
- try user.encode(to: encoder)
- case .document(let document):
- try container.encode("document", forKey: .type)
- try document.encode(to: encoder)
- }
- }
- }
- let items = try JSONDecoder().decode([Item].self, from: json)
- print(items)
- let output = try JSONEncoder().encode(items)
- print(String(data: output, encoding: .utf8)!)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement