I think you only need serialize the .identifier
string value and on decode, read the .identifier
back and call .init(identifier:)
.
How to implement Codable
for this?
I think you only need serialize the .identifier
string value and on decode, read the .identifier
back and call .init(identifier:)
.
How to implement Codable
for this?
TimeZone
already conforms to Encodable
and Decodable
(i.e., Codable
).
In general, it is not advisable to conform types that you don't own to protocols that you also don't own. If you need to do something like that, consider creating your own wrapper class and conforming that class to the protocol in question.
Sorry I didn't look before I ask. I have something just like TimeZone
: only a predefined list of these things, keyed with an identifier: String
:
struct MyThing {
let identifier: String // unique id
let otherValues: Int
// lots of other properties
init(identifier: String)? {
// something like this:
if let result = Self.knownList.first { $0.identifier == identifier } {
self = result
}
return nil
}
static knownList: [MyThing] = [
.init(identifier: "xxxx", otherValues: 100, ....)
// all possible MyThing are defined here
]
}
I want to make MyThing: Coable
Answer:
import Foundation
let encoder = JSONEncoder()
let decoder = JSONDecoder()
struct Big {
let location: String
let city: String
let region: String?
let timezone: TimeZone
// anyway to not have to define? someway to use just default?
enum CodingKeys: String, CodingKey {
case location
}
static let knownList: [Self] = [
Big(location: "A", city: "London", region: "UK", timezone: TimeZone(identifier: "Europe/London")!),
Big(location: "B", city: "Another City", region: "Nowhere", timezone: TimeZone(identifier: "America/Cancun")!),
]
}
extension Big: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(location, forKey: .location)
}
}
extension Big: Decodable {
enum DecodeError: Error {
case keyNotFound(String)
}
init(from decoder: Decoder) throws {
let value = try decoder.container(keyedBy: CodingKeys.self).decode(String.self, forKey: .location)
guard let found = Big.knownList.first(where: { $0.location == value }) else {
throw DecodeError.keyNotFound(value)
}
self = found
}
}
let a = Big.knownList[1]
let data = try encoder.encode(a)
let string = String(data: data, encoding: .utf8)!
print(string)
let reincarnated = try decoder.decode(Big.self, from: data)
print(reincarnated)
Hopefully something like this work with NSKeyedArchiver