I'm working with SAP Cloud Platform SDK for iOS, trying to figure out how to put an array of EntityValue
s into a CompositeStorage
, and get them out. I'm getting error:
typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [Foundation.(_PlistKey in _5692656F4C05BA2A580AE9322E9FB0A6)(stringValue: "Index 0", intValue: Optional(0)), Foundation.(_PlistKey in _5692656F4C05BA2A580AE9322E9FB0A6)(stringValue: "Index 0", intValue: Optional(0))], debugDescription: "Expected to decode Dictionary but found __NSCFData instead.", underlyingError: nil))
I'm trying to get the values from the CompositeStore
here:
var entities: [ExpensereportType] {
do {
guard let results = try Cache.shared.store.get(Array<ExpensereportType>.self, for: CollectionType.expensereport.rawValue) else {
return []
}
return results
}
catch {
print(error)
return []
}
}
And they're being encoded here:
self.service.fetchReservation(matching: query) { result, error in
guard let result = result else { return completionHandler(error!) }
do {
let encodedResult = try JSONEncoder().encode(result)
try self.store.put(encodedResult, for: CollectionType.reservation.rawValue)
}
catch {
completionHandler(error)
}
completionHandler(nil)
}
Any ideas?
The solution for this one is interesting: it turns out that the JSONEncoder
is smart enough to handle either the Array<EntityValue>
as-is, or have the individual items be map-encoded. But, the JSONDecoder
automatically handles the top-level Array item, and it is up to you to map-decode the items.
Working solution:
// MARK: - Encode
self.service.fetchReservation(matching: query) { result, error in
guard let result = result else {
completionHandler(error!)
return
}
do {
let encodedResult = try JSONEncoder().encode(result)
// try result.map { try JSONEncoder().encode($0) } ALSO VALID
try self.store.put(encodedResult, for: CollectionType.expensereport.rawValue)
}
//...
// MARK: - Decode `Array<ExpensereportType>`
guard let results = try Cache.shared.store.get(Array<ExpensereportType>.self, for: CollectionType.expensereport.rawValue) else {
return []
}
let decoder = JSONDecoder()
decoder.userInfo.updateValue(myDataService.metadata, forKey: CSDLDocument.csdlInfoKey)
return try results.map { try decoder.decode(ExpensereportType.self, from: $0)}