Skip to content

Commit 755246a

Browse files
committed
Implement Codable conformance
1 parent c0072c2 commit 755246a

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

iCookTV/Models/Category.swift

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
// SOFTWARE.
2525
//
2626

27+
import Foundation
2728
import Freddy
2829

29-
struct Category: JSONDecodable {
30+
struct Category: Codable, JSONDecodable {
3031

3132
let id: String
3233
let name: String
@@ -40,4 +41,34 @@ struct Category: JSONDecodable {
4041
coverURLs = try value.getArray(at: "attributes", "cover-urls").map(String.init)
4142
}
4243

44+
// MARK: - Codable
45+
46+
private enum CodingKeys: String, CodingKey {
47+
case id
48+
case attributes
49+
}
50+
51+
private enum AttributesCodingKeys: String, CodingKey {
52+
case name
53+
case coverURLs = "cover-urls"
54+
}
55+
56+
init(from decoder: Decoder) throws {
57+
let container = try decoder.container(keyedBy: CodingKeys.self)
58+
id = try container.decode(String.self, forKey: .id)
59+
60+
let attributes = try container.nestedContainer(keyedBy: AttributesCodingKeys.self, forKey: .attributes)
61+
name = try attributes.decode(String.self, forKey: .name)
62+
coverURLs = try attributes.decode([String].self, forKey: .coverURLs)
63+
}
64+
65+
func encode(to encoder: Encoder) throws {
66+
var container = encoder.container(keyedBy: CodingKeys.self)
67+
try container.encode(id, forKey: .id)
68+
69+
var attributes = container.nestedContainer(keyedBy: AttributesCodingKeys.self, forKey: .attributes)
70+
try attributes.encode(name, forKey: .name)
71+
try attributes.encode(coverURLs, forKey: .coverURLs)
72+
}
73+
4374
}

iCookTV/Models/Video.swift

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import Foundation
2828
import Freddy
2929

30-
struct Video: JSONDecodable, JSONEncodable {
30+
struct Video: Codable, JSONDecodable, JSONEncodable {
3131

3232
let id: String
3333
let title: String
@@ -93,4 +93,51 @@ struct Video: JSONDecodable, JSONEncodable {
9393
return .dictionary(json)
9494
}
9595

96+
// MARK: - Codable
97+
98+
private enum CodingKeys: String, CodingKey {
99+
case id
100+
case attributes
101+
}
102+
103+
private enum AttributesCodingKeys: String, CodingKey {
104+
case title
105+
case subtitle
106+
case description
107+
case length
108+
case youtube = "embed-url"
109+
case source = "video-url"
110+
case cover = "cover-url"
111+
}
112+
113+
init(from decoder: Decoder) throws {
114+
let container = try decoder.container(keyedBy: CodingKeys.self)
115+
id = try container.decode(String.self, forKey: .id)
116+
117+
let attributes = try container.nestedContainer(keyedBy: AttributesCodingKeys.self, forKey: .attributes)
118+
title = try attributes.decode(String.self, forKey: .title)
119+
subtitle = try? attributes.decode(String.self, forKey: .subtitle)
120+
description = try? attributes.decode(String.self, forKey: .description)
121+
length = (try? attributes.decode(Int.self, forKey: .length)) ?? 0
122+
youtube = try attributes.decode(String.self, forKey: .youtube)
123+
source = try? attributes.decode(String.self, forKey: .source)
124+
cover = try attributes.decode(String.self, forKey: .cover)
125+
}
126+
127+
func encode(to encoder: Encoder) throws {
128+
var container = encoder.container(keyedBy: CodingKeys.self)
129+
try container.encode(id, forKey: .id)
130+
131+
var attributes = container.nestedContainer(keyedBy: AttributesCodingKeys.self, forKey: .attributes)
132+
try attributes.encode(title, forKey: .title)
133+
try attributes.encode(length, forKey: .length)
134+
try attributes.encode(youtube, forKey: .youtube)
135+
try attributes.encode(cover, forKey: .cover)
136+
137+
// Optional values
138+
try subtitle.map { try attributes.encode($0, forKey: .subtitle) }
139+
try description.map { try attributes.encode($0, forKey: .description) }
140+
try source.map { try attributes.encode($0, forKey: .source) }
141+
}
142+
96143
}

iCookTVTests/CategorySpec.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
//
2626

2727
@testable import iCookTV
28-
import Freddy
2928
import Nimble
3029
import Quick
3130

@@ -35,10 +34,10 @@ class CategorySpec: QuickSpec {
3534

3635
let data: Data = Resources.testData(named: "Category.json")!
3736

38-
describe("init(json:)") {
37+
describe("decoding") {
3938
it("should parse JSON as Category") {
40-
let json = try! JSON(data: data)
41-
let category = try! Category(json: json)
39+
let decoder = JSONDecoder()
40+
let category = try! decoder.decode(Category.self, from: data)
4241

4342
expect(category.id).to(equal("9527"))
4443
expect(category.name).to(equal("愛料理廚房"))

iCookTVTests/VideoSpec.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ class VideoSpec: QuickSpec {
3535

3636
let data: Data = Resources.testData(named: "Video.json")!
3737
let json = try! JSON(data: data as Data)
38-
let video = try! Video(json: json)
3938

40-
describe("init(json:)") {
39+
let decoder = JSONDecoder()
40+
let video = try! decoder.decode(Video.self, from: data)
41+
42+
describe("decoding") {
4143
it("should parse JSON as Video") {
4244
expect(video.id).to(equal("42"))
4345
expect(video.title).to(equal("Lorem"))

0 commit comments

Comments
 (0)