'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