iOS returns json data from background notifications with the type [AnyHashable : Any]
.
Is there any way to parse that into an struct that implements the Codable protocol?
example :
// Server sends the following data via apn
{"items": [{"id": "192e7926-7891-44eb-8ca7-f795d8552e84", "text": "some text", "num": 0.7}]}
When receiving the data on th eapp side
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo["items"])
}
the print statement give sthe following output
Optional(<__NSSingleObjectArrayI 0x283fe80b0>(
{
id = "192e7926-7891-44eb-8ca7-f795d8552e84";
num = "0.7";
text = "Check test";
}
))
I already have a matching Codable struct:
struct Item: Codable {
let id: UUID
let text: String
let num: Double
}
Can I somehow instantiate an Item
from a userInfo["items"][0]
? Obviously just sending an encoded json string would already solve that but I'm interested if there is a way to decode from [AnyHashable : Any] into an Decodable
struct.
Thanks!
You can convert the dict to JSON object using JSONSerialization.data(withJSONObject:
You might need a container struct
struct ItemsCollection: Decodable {
let items: [Item]
}
let dict: [AnyHashable: Any] = your dict
do {
let jsonData = try JSONSerialization.data(withJSONObject: dict)
let itemsCollection = try JSONDecoder().decode(ItemsCollection.self, from: jsonData)
//now access it as itemsCollection.items[0]
}
catch {
print(error)
}
EDIT 1: You can always optimize the solution by avoiding the creation of new struct using
let dict: [AnyHashable: Any] = userInfo["items"][0] //not sure if you would need explicit type casting here, cant debug as I dont have actual object
do {
let jsonData = try JSONSerialization.data(withJSONObject: dict)
let item = try JSONDecoder().decode(Item.self, from: jsonData)
//now access item
}
catch {
print(error)
}