2

I'm trying to parse data from the server, but I get this error:

failure(Swift.DecodingError.typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil)))

The parameters should be passed as an array of objects, as well as the response object. I can't figure out what should I change in my code so the response is well structured. This is what a response looks like:

[
  {
   'code' : number, 
   'error' => boolean, 
   'code_error' => number, 
   'data_error' => string, 
   'message' => 'Falta Campo requerido'
  }
]

These are the parameters that should be passed:

[
   {
      'email' => 'required|string|email',
      'event_type' => 'required|string',
      'watermark' => 'required|string',
      'date' => 'required',
      'location' => 'required|string',
      'segment' => 'required',
      'time' => 'required',
      'country' => 'required',
      'city' => 'required'
    }
]

And this is what my code looks like.

Data:

struct MarcaAguaResData: Codable {
    let code: Int
    let error: Bool
    let message: String
}

struct MarcaAguaErrorResponse: Decodable, LocalizedError {
    let code: Int
    let error: Bool
    let message: String
    let code_error: Int
    let data_error: String
}

Server:

class MarcaAguaService {
    func marcaAgua(parameters: [String: Any],
                completion: @escaping (Result<MarcaAguaResData, Error>)-> Void) {
    
    let urlString =  baseUrl + "events"
    
    guard let url = URL(string: urlString) else {
        completion(.failure(NetworkingError.badUrl))
        return
    }
    
    var request = URLRequest(url: url)
    var components = URLComponents()
    var queryItems = [URLQueryItem]()
    
    for (key, value) in parameters {
        let queryItem = URLQueryItem(name: key, value: String(describing: value))
        queryItems.append(queryItem)
    }
    
    
    components.queryItems = queryItems
    
    let queryItemsData = components.query?.data(using: .utf8)
    
    request.httpBody = queryItemsData
    request.httpMethod = "POST"
    request.setValue("Bearer \(token_login)", forHTTPHeaderField: "Authorization")
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let session = URLSession.shared
    
    let task = session.dataTask(with: request) { (data, response, error) in
        DispatchQueue.main.async {
            guard let unwrappedResponse = response as? HTTPURLResponse else {
                completion(.failure(NetworkingError.badResponse))
                return
            }
            
            switch unwrappedResponse.statusCode {
            case 200 ..< 300:
                print("success")
            default:
                print("failure")
            }
            
            if let unwrappedError = error {
                completion(.failure(unwrappedError))
                return
            }
            
            if let unwrappedData = data {
                do{
                    let json = try JSONSerialization.jsonObject(with: unwrappedData, options: .allowFragments)
                    print("BBBB")
                    print(json)
                    
                    if let successRes = try? JSONDecoder().decode(MarcaAguaResData.self, from: unwrappedData){
                        completion(.success(successRes))
                    }else{
                      
                        let errorResponse = try JSONDecoder().decode(MarcaAguaErrorResponse.self, from: unwrappedData)
                        print("Error \(errorResponse)")
                        completion(.failure(errorResponse))
                    }
                }catch{
                    print("AAA")
                    completion(.failure(error))
                }
            }
        }
    }
    task.resume()
}
}
4
  • 1
    decode(CodableStruct.self, means you expect an object CodableStruct at top level of your JSON. decode([CodableStruct].self, means you expect an array of CodableStruct at top level of your JSON. You are sending an array, so you aren't decoding correctly... Commented Jul 8, 2021 at 15:12
  • 1
    Side note, you are sending queryItemsData which is in form or url encoded data, and not JSON? It's strange, since you receive JSON, and you put in content-type, JSON... Commented Jul 8, 2021 at 15:14
  • What do you recommend me to do? Commented Jul 8, 2021 at 15:18
  • request.httpBody = try? JSONSerialization.data(withJSONObject: parameters) or request.httpBody = try? JSONSerialization.data(withJSONObject: [parameters]) (it's unclear if you send only one or an array of objects). For your decoding fix, MarcaAguaErrorResponse.self -> [MarcaAguaErrorResponse].self` Might be the same diff in success: MarcaAguaResData.self => [MarcaAguaResData].self Commented Jul 8, 2021 at 16:34

1 Answer 1

1

To be [MarcaAguaResData].self which is an array instead of MarcaAguaResData.self which is a dictionary

 if let successRes = try? JSONDecoder().decode([MarcaAguaResData].self, from: unwrappedData){
   completion(.success(successRes))
 }else{
    let errorResponse = try JSONDecoder().decode([MarcaAguaErrorResponse].self, from: unwrappedData)
    print("Error \(errorResponse)")
    completion(.failure(errorResponse))
 }

With

completion: @escaping (Result<[MarcaAguaResData], Error>)-> Void)
Sign up to request clarification or add additional context in comments.

3 Comments

Still not sending data to the server. That helped, but I don't know if I'm missing something in the parameters section
what print(json) gives answer has no relation to sent data
@Sh_Khan pls check your mail

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.