-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathContentstackResponse.swift
More file actions
114 lines (99 loc) · 4.99 KB
/
ContentstackResponse.swift
File metadata and controls
114 lines (99 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//
// ContentstackResponse.swift
// Contentstack
//
// Created by Uttam Ukkoji on 18/03/20.
//
import Foundation
private protocol ResponseParams {
var count: UInt? { get }
}
private protocol HomogeneousResponse: ResponseParams {
associatedtype ItemType
var items: [ItemType] { get }
}
internal enum ResponseCodingKeys: String, CodingKey {
case entries, entry, assets, asset, skip, limit, errors, count, globalFields, globalField
case contentTypes = "content_types", contentType = "content_type"
}
/// This is the result of any request of collection from Contentstack.
public final class ContentstackResponse<ItemType>: HomogeneousResponse, Decodable
where ItemType: EndpointAccessible & Decodable {
/// The resources which are part of the array response.
public var items: [ItemType] = []
/// The maximum number of resources originally requested.
public var limit: UInt?
/// The number of elements skipped when performing the request.
public var skip: UInt?
/// The total number of resources which matched the original request.
public var count: UInt?
/// The dictionary of fields from the response that are included in API request.
public var fields: [String: Any]?
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ResponseCodingKeys.self)
self.limit = try container.decodeIfPresent(UInt.self, forKey: .limit)
self.skip = try container.decodeIfPresent(UInt.self, forKey: .skip)
self.count = try container.decodeIfPresent(UInt.self, forKey: .count)
self.items = []
switch ItemType.endpoint {
case .assets:
if let assets = try container.decodeIfPresent([ItemType].self, forKey: .assets) {
self.items = assets
} else if let asset = try container.decodeIfPresent(ItemType.self, forKey: .asset) {
self.items = [asset]
}
case .contenttype:
if let contentTypes = try container
.decodeIfPresent([ItemType].self, forKey: .contentTypes) {
self.items = contentTypes
} else if let contentType = try container
.decodeIfPresent(ItemType.self, forKey: .contentType) {
self.items = [contentType]
}
case .entries:
if let entries = try container.decodeIfPresent([ItemType].self, forKey: .entries) {
let containerFields = try decoder.container(keyedBy: JSONCodingKeys.self)
let response = try containerFields.decode(Dictionary<String, Any>.self)
if let contentType = response["content_type"] as? ContentTypeModel {
fields = ["content_type": contentType]
}
self.items = entries
} else if let entry = try container.decodeIfPresent(ItemType.self, forKey: .entry) {
if var contentTypeIncludable = entry as? ContentTypeIncludable {
let containerFields = try decoder.container(keyedBy: JSONCodingKeys.self)
let response = try containerFields.decode(Dictionary<String, Any>.self)
if let contentType = response["content_type"] as? ContentTypeModel {
contentTypeIncludable.contentType = contentType
}
}
self.items = [entry]
}
case .taxnomies:
if let taxonomies = try container.decodeIfPresent([ItemType].self, forKey: .entries) {
let containerFields = try decoder.container(keyedBy: JSONCodingKeys.self)
let response = try containerFields.decode(Dictionary<String, Any>.self)
if let contentType = response["content_type"] as? ContentTypeModel {
fields = ["content_type": contentType]
}
self.items = taxonomies
}
case .globalfields:
// Decode entire response as [String: AnyDecodable] using singleValueContainer
let fullResponseContainer = try decoder.singleValueContainer()
let fullResponse = try fullResponseContainer.decode([String: AnyDecodable].self)
if let globalFieldsArray = fullResponse["global_fields"]?.value as? [[String: Any]] {
for item in globalFieldsArray {
let data = try JSONSerialization.data(withJSONObject: item, options: [])
let model = try JSONDecoder().decode(ItemType.self, from: data)
self.items.append(model)
}
} else if let globalField = fullResponse["global_field"]?.value as? [String: Any] {
let data = try JSONSerialization.data(withJSONObject: globalField, options: [])
let model = try JSONDecoder().decode(ItemType.self, from: data)
self.items = [model]
}
default:
ContentstackLogger.log(.error, message: ContentstackMessages.unsupportedEndpointType)
}
}
}