I have the following structure of code. If I omit the codingkey part the code is running. I implemented StringConverter to convert a string to Int (from bySundell Swift Side)
struct Video: Codable {
var title: String
var description: String
var url: URL
var thumbnailImageURL: URL
var numberOfLikes: Int {
get { return likes.value }
}
private var likes: StringBacked<Int>
enum CodingKeys: String, CodingKey{
case title = "xxx"
case description = "jjjj"
case url = "url"
case thumbnailImageURL = "jjjjjjjj"
case numberofLikes = "jjjjjkkkk"
}
}
// here the code for converting the likes
protocol StringRepresentable: CustomStringConvertible {
init?(_ string: String)
}
extension Int: StringRepresentable {}
struct StringBacked<Value: StringRepresentable>: Codable {
var value: Value
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
let stringToConvert = string.split(separator: "/").last!.description
guard let value = Value(stringToConvert) else {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: """
Failed to convert an instance of \(Value.self) from "\(string)"
"""
)
}
self.value = value
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(value.description)
}}
As i said, if I omit the Codingkeys part it does me show no error. I would simply create a struct, where I get a string from a Rest API and I want to convert in an Int for my database using Codable. Thanks Arnold
When you define CodingKeys
, you need to provide key for each non-optional/non-initialized property so that compiler know how to initialize while decoding. Applying this to Video
, it will look like this,
struct Video: Codable {
var title: String
var description: String
var url: URL
var thumbnailImageURL: URL
var numberOfLikes: Int {
return likes.value
}
private var likes: StringBacked<Int>
enum CodingKeys: String, CodingKey{
case title = "xxx"
case description = "jjjj"
case url = "url"
case thumbnailImageURL = "jjjjjjjj"
case likes = "jjjjjkkkk"
}
}
If you see closely, this property private var likes: StringBacked<Int>
was not provided any CodingKey
in the enum so compiler was complaining. I updated the enum with this case case likes = "jjjjjkkkk"
and removed case numberofLikes = "jjjjjkkkk"
because numberofLikes
is a read only computed property that doesn't need any parsing.