Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit 061b616

Browse files
committed
Update StatsDotComFollowersInsight to use Codable
1 parent 060bd54 commit 061b616

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed
Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public struct StatsDotComFollowersInsight {
1+
public struct StatsDotComFollowersInsight: Codable {
22
public let dotComFollowersCount: Int
33
public let topDotComFollowers: [StatsFollower]
44

@@ -7,6 +7,11 @@ public struct StatsDotComFollowersInsight {
77
self.dotComFollowersCount = dotComFollowersCount
88
self.topDotComFollowers = topDotComFollowers
99
}
10+
11+
private enum CodingKeys: String, CodingKey {
12+
case dotComFollowersCount = "total_wpcom"
13+
case topDotComFollowers = "subscribers"
14+
}
1015
}
1116

1217
extension StatsDotComFollowersInsight: StatsInsightData {
@@ -22,24 +27,19 @@ extension StatsDotComFollowersInsight: StatsInsightData {
2227
}
2328

2429
public init?(jsonDictionary: [String: AnyObject]) {
25-
guard
26-
let subscribersCount = jsonDictionary["total_wpcom"] as? Int,
27-
let subscribers = jsonDictionary["subscribers"] as? [[String: AnyObject]]
28-
else {
29-
return nil
30+
do {
31+
let jsonData = try JSONSerialization.data(withJSONObject: jsonDictionary, options: [])
32+
let decoder = JSONDecoder()
33+
self = try decoder.decode(StatsDotComFollowersInsight.self, from: jsonData)
34+
} catch {
35+
return nil
3036
}
31-
32-
let followers = subscribers.compactMap { StatsFollower(jsonDictionary: $0) }
33-
34-
self.dotComFollowersCount = subscribersCount
35-
self.topDotComFollowers = followers
3637
}
3738

38-
// MARK: -
3939
fileprivate static let dateFormatter = ISO8601DateFormatter()
4040
}
4141

42-
public struct StatsFollower {
42+
public struct StatsFollower: Codable {
4343
public let id: String?
4444
public let name: String
4545
public let subscribedDate: Date
@@ -54,39 +54,50 @@ public struct StatsFollower {
5454
self.avatarURL = avatarURL
5555
self.id = id
5656
}
57+
58+
private enum CodingKeys: String, CodingKey {
59+
case id = "ID"
60+
case name = "label"
61+
case subscribedDate = "date_subscribed"
62+
case avatarURL = "avatar"
63+
}
5764
}
5865

5966
extension StatsFollower {
60-
61-
init?(jsonDictionary: [String: AnyObject]) {
62-
guard
63-
let name = jsonDictionary["label"] as? String,
64-
let avatar = jsonDictionary["avatar"] as? String,
65-
let dateString = jsonDictionary["date_subscribed"] as? String
66-
else {
67-
return nil
67+
public init(from decoder: Decoder) throws {
68+
let container = try decoder.container(keyedBy: CodingKeys.self)
69+
self.name = try container.decode(String.self, forKey: .name)
70+
if let id = try? container.decodeIfPresent(Int.self, forKey: .id) {
71+
self.id = "\(id)"
72+
} else if let id = try? container.decodeIfPresent(String.self, forKey: .id) {
73+
self.id = id
74+
} else {
75+
self.id = nil
6876
}
69-
let id = jsonDictionary["ID"] as? String
70-
self.init(name: name, avatar: avatar, date: dateString, id: id)
71-
}
7277

73-
init?(name: String, avatar: String, date: String, id: String? = nil) {
74-
guard let date = StatsDotComFollowersInsight.dateFormatter.date(from: date) else {
75-
return nil
78+
let avatar = try? container.decodeIfPresent(String.self, forKey: .avatarURL)
79+
if let avatar, var components = URLComponents(string: avatar) {
80+
components.query = "d=mm&s=60" // to get a properly-sized avatar.
81+
self.avatarURL = components.url
82+
} else {
83+
self.avatarURL = nil
7684
}
7785

78-
let url: URL?
79-
80-
if var components = URLComponents(string: avatar) {
81-
components.query = "d=mm&s=60" // to get a properly-sized avatar.
82-
url = components.url
86+
let dateString = try container.decode(String.self, forKey: .subscribedDate)
87+
if let date = StatsDotComFollowersInsight.dateFormatter.date(from: dateString) {
88+
self.subscribedDate = date
8389
} else {
84-
url = nil
90+
throw DecodingError.dataCorruptedError(forKey: .subscribedDate, in: container, debugDescription: "Date string does not match format expected by formatter.")
8591
}
92+
}
8693

87-
self.name = name
88-
self.subscribedDate = date
89-
self.avatarURL = url
90-
self.id = id
94+
init?(jsonDictionary: [String: AnyObject]) {
95+
do {
96+
let jsonData = try JSONSerialization.data(withJSONObject: jsonDictionary, options: [])
97+
let decoder = JSONDecoder()
98+
self = try decoder.decode(StatsFollower.self, from: jsonData)
99+
} catch {
100+
return nil
101+
}
91102
}
92103
}

0 commit comments

Comments
 (0)