简体   繁体   中英

Cannot convert value of type 'Dictionary<String, Any>?' to expected argument type 'Data'

I am still new to swift and i am trying to fetch json data and pass it to the next view as an object which i created. However, i am getting this error Cannot convert value of type 'Dictionary?' to expected argument type 'Data' when i try to user the decoder class. I am not sure what to do to fix it. I have tried changing Dictionary?' to Data in my completion handler but i am still getting errors.

This is my code :

Service call

    class ServiceCall: NSObject, ServiceCallProtocol, URLSessionDelegate {



    let urlServiceCall: String?
    let country: String?
    let phone: String?
     var search: SearchResultObj?

    init(urlServiceCall: String,country: String, phone: String){
        self.urlServiceCall = urlServiceCall
        self.country = country
        self.phone = phone
    }


    func fetchJson(request: URLRequest, customerCountry: String, mobileNumber: String, completion: ((Bool, Dictionary<String, Any>?) -> Void)?){

        let searchParamas = CustomerSearch.init(country: customerCountry, phoneNumber: mobileNumber)
        var request = request
        request.httpMethod = "POST"
        request.httpBody = try?  searchParamas.jsonData()
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        let session = URLSession.shared
        let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
            do {
                let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, Any>
                let status = json["status"] as? Bool
                if status == true {
                    print(json)
                }else{
                    print(" Terrible failure")
                }
            } catch {
               print("Unable to make an api call")
            }
        })

        task.resume()

    }


  }

SearchViewModel

func searchDataRequested(_ apiUrl: String,_ country: String,_ phone:String) {

    let service = ServiceCall(urlServiceCall: apiUrl, country: country, phone: phone)
    let url = URL(string: apiUrl)
    let request = URLRequest(url: url!)
    let country = country
    let phone = phone

    service.fetchJson(request: request, customerCountry: country, mobileNumber: phone)
    { (ok, json) in
        print("CallBack response : \(String(describing: json))")
        let decoder = JSONDecoder()
        let result = decoder.decode(SearchResultObj.self, from: json)

        print(result.name)
        // self.jsonMappingToSearch(json as AnyObject)

    }
}

New error:

在此处输入图片说明

You are going to deserialize the JSON twice which cannot work.

Instead of returning a Dictionary return Data , this mistake causes the error, but there are more issues.

func fetchJson(request: URLRequest, customerCountry: String, mobileNumber: String, completion: (Bool, Data?) -> Void) { ...

Then change the data task to

let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in

    if let error = error { 
        print("Unable to make an api call", error)
        completion(false, nil)
        return 
    }
    completion(true, data)
})

and the service call

service.fetchJson(request: request, customerCountry: country, mobileNumber: phone) { (ok, data) in
    if ok {
        print("CallBack response :", String(data: data!, encoding: .utf8))
        do {
            let result = try JSONDecoder().decode(SearchResultObj.self, from: data!)
            print(result.name)
            // self.jsonMappingToSearch(json as AnyObject)
        } catch { print(error) }
    }
}

And you have to adopt Decodable in ServiceCall

class ServiceCall: NSObject, ServiceCallProtocol, URLSessionDelegate, Decodable { ...

Further I highly recommended to separate the class model from the code to retrieve the data.

The data returned from session's task can either be serialized with JSONSerialization or decode it with JSONDecoder

 let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in

either

 let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, Any>

OR

let result = try  decoder.decode([item].self,data!)

the second argument of the decode method expects a parameter of type Data not Dictionary

you have to only edit the completion of fetchJson to return Bool,Data instead of Bool,Dictionary,and remove JSONSerialization code from it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM