'Faild to Map data to decodable object Moya Swift
Hi i want to get a code string from json API to label and i am getting an error as Faild to Map data to decodable object. I debug and get request failure error as here.
objectMapping(Swift.DecodingError.typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))
Here is my code
struct Benefits: Codable {
var benefitsCode:String?
enum CodingKeys:String, CodingKey {
case benefitsCode = "benefitsCode"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
benefitsCode = try values.decodeIfPresent(String.self, forKey: .benefitsCode)
}
}
Model Class
final class BenefitsModel: EventNode {
weak var output: BenefitsModelOutput!
private var benefits: [Benefits] = []
private var benefitsProvider = DataManager<BenefitsAPI, [Benefits]>()
override init(parent: EventNode?) {
super.init(parent: parent)
}
private func load() {
benefitsProvider.load(target: .benefitsCode, withActivity: true) {[weak self] result in
switch result {
case .success(let response):
print(response,"here chck")
self?.benefits = response
self?.output.perform(action: .didLoad)
case .failure(let error):
print(error)
}
}
Here is the Json from API
{
"name": String, "surname": String, "benefitsCode": String, "facebookShareText": String, "twitterShareText": String, "mailShareText": String, "amountOfUses": int
}
API layer fetch is
enum BenefitsAPI {
case benefitsCode
}
extension BenefitsAPI: TargetType, AccessTokenAuthorizable {
var path: String {
switch self {
case .benefitsCode: return "/api/benefits"
}
}
var method: Moya.Method {
switch self {
case .benefitsCode: return .get
}
}
var task: Task {
switch self {
case .benefitsCode: return .requestPlain
}
}
var authorizationType: AuthorizationType? {
.bearer
}
}
Solution 1:[1]
As you haven't supplied the load function that does the loading and decoding it's not possible to provide a full answer as that is the most relevant code.
Also the JSON you have provided is not valid JSON. It looks more like an interface definition than the returned data. However, for the sake of demonstrating the approach, let's convert it to valid JSON:
{
"name": "String",
"surname": "String",
"benefitsCode": "String",
"facebookShareText": "String",
"twitterShareText": "String",
"mailShareText": "String",
"amountOfUses": "int"
}
It's relatively obvious that this represents a single record, not an array of records, but as the record has the key in it you are looking for we'll again continue to demonstrate the approach. Therefore to get that data out you just need to
let jsonData = Data(json.utf8)
//where json is the String of JSON above
let benefit = try! JSONDecoder().decode(Benfit.self, from: jsonData).
//real world code should use `do ... try ... catch` not 'try!`
print(benefit)
// prints: Benefits(benefitsCode: Optional("String"))
Solution 2:[2]
AS @flanker comment i just need to configure the data manager to return the data provided by the API, to change it to return a single object rather than an array. The model is fine to decode.
var benefits:Benefits!
private var benefitsProvider = DataManager<BenefitsAPI, Benefits>()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | flanker |
| Solution 2 | Flying |
