I am creating a generic post body for my API's call, my post body is mostly same except the data parameter which is different for different API calls data acts like filler for different requirements, few below JSON post body.
Example 1:
{
"timeStampUtc": "2019-07-29T03:29:21.729Z",
...
"geoLocationInfo": {
"latitude": 0,
"longitude": 0,
...
},
"data": {
"loginIdentity": "string",
"loginPassword": "string"
}
}
Example 2:
{
"timeStampUtc": "2019-07-29T03:29:21.729Z",
...
"geoLocationInfo": {
"latitude": 0,
"longitude": 0,
...
},
"data": {
"wazId": 0,
"regionId": 0
}
}
Example 3:
{
"timeStampUtc": "2019-07-29T03:29:21.729Z",
...
"geoLocationInfo": {
"latitude": 0,
"longitude": 0,
...
},
"data": {
"loginIdentity": "string",
"wazID": 0
}
}
I am using the encodable and generics to overcome this requirement, well I am able to do the first two scenarios, but struggle with the third when the data has values of different types. Following is the sample code can be directly tried in Playground
struct PostBody<T : Codable>: Codable
{
var deviceInfo = ""
var geoLocationInfo = ""
var data = Dictionary<String, T>()
enum CodingKeys: String, CodingKey
{
case deviceInfo, geoLocationInfo, data
}
init(dataDict : Dictionary<String, T>) {
self.data = dataDict
}
init(from decoder : Decoder) throws {
let container = try decoder.container(keyedBy : CodingKeys.self)
deviceInfo = try container.decode(String.self, forKey: .deviceInfo)
geoLocationInfo = try container.decode(String.self, forKey: .geoLocationInfo)
data = try container.decode(Dictionary.self, forKey: .data)
}
func encode(to encoder : Encoder)
{
var container = encoder.container(keyedBy : CodingKeys.self)
do
{
try container.encode(deviceInfo, forKey : .deviceInfo)
try container.encode(geoLocationInfo, forKey : .geoLocationInfo)
try container.encode(data, forKey : .data)
}
catch
{
fatalError("Should never happen")
}
}
}
let postBody = PostBody<String>(dataDict : ["1" : "1", "2" : "2"])
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
try encoder.encode(postBody)
let encodedDataDict2 = try encoder.encode(postBody)
print(String(data : encodedDataDict2, encoding : .utf8)!)
let postBody1 = PostBody(dataDict : ["1" : 1, "2" : 2])
let encoder1 = JSONEncoder()
encoder1.outputFormatting = .prettyPrinted
try encoder1.encode(postBody1)
let encodedDataDict3 = try encoder1.encode(postBody1)
print(String(data : encodedDataDict3, encoding : .utf8)!)