mbuchetics
6/30/2017 - 9:30 AM

Implement Codable on an enum

Implement Codable on an enum

struct User: Codable {
    var name: String
    var email: String
    var id: String
    var metadata: [String: MetadataType]

    enum CodingKeys: String, CodingKey {
        case name, email, id, metadata
    }
}

enum MetadataType: Codable {
    case double(Double)
    case string(String)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        do {
            self = try .double(container.decode(Double.self))
        } catch DecodingError.typeMismatch {
            do {
                self = try .string(container.decode(String.self))
            } catch DecodingError.typeMismatch {
                throw DecodingError.typeMismatch(MetadataType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Encoded payload not of an expected type"))
            }
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .double(let double):
            try container.encode(double)
        case .string(let string):
            try container.encode(string)
        }
    }
}

import Foundation

let decoder = JSONDecoder()

let userJson = """
    {
    "id": "4yq6txdpfadhbaqnwp3",
    "email": "john.doe@example.com",
    "name":"John Doe",
    "metadata": {
      "link_id": "linked-id",
      "buy_count": 4
    }
  }
""".data(using: .utf8)!

let user = try! decoder.decode(User.self, from: userJson)
print(user)

let encoder = PropertyListEncoder()
encoder.outputFormat = .xml
let plist = try! encoder.encode(user)
print(String(data: plist, encoding: .utf8)!)