We can implement our own logic when encoding/decoding objects. Imagine we have a JSON structure that provides the width and height of a rectangle, but we want to store that information in a CGSize
property.
let json: String = """
{
"width": 35,
"height": 25
}
"""
struct MyRectangle: Codable {
let size: CGSize
// 1
enum CodingKeys: String, CodingKey {
case height
case width
}
// 2
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let width = try values.decode(Double.self, forKey: .width)
let height = try values.decode(Double.self, forKey: .height)
size = CGSize(width: width, height: height)
}
// 3
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(size.width, forKey: .width)
try container.encode(size.height, forKey: .height)
}
}
1. CodingKeys
The first step is to define the enum CodingKeys
as we've seen in previous articles.
2. Decoder
To decode, we can implement the init
from the Decodable protocol, where we’ll have a container that is retrieved by passing our enum CodingKeys
. This allows us to get the values using the defined cases. Once we obtain width
and height
, we can initialize our size
property.
3. Encoder
In this case, we retrieve the container in the same way, but this time we use the encode()
function to include the necessary information, which we get from the size
property.
Be the first to comment