1

So I am trying to call backend api to get an object of type horse, I get the object in data but when I try to decode it, it does not work. How can I fix that? You can see my Message Model and my Horse Model. I tried to find a difference between them and the json but I could not.

Message Model

 //
//  MessageType.swift
//  HorseStable
//
//  Created by Student on 30/12/2019.
//  Copyright © 2019 smartmobile. All rights reserved.
//

import Foundation

enum MessageType : Int,Decodable {
         case CREATE_HORSE
          case GET_HORSE
          case UPDATE_HORSE
          case DELETE_HORSE
          case GET_HORSES_ASSIGNED_TO_USER
          case REMOVE_HORSE_FROM_USER
          case ADD_HORSE_TO_USER
      /* USERS */
      case CREATE_USER
      case GET_USER
      case UPDATE_USER
      case DELETE_USER

      /* FACILITIES */
      case CREATE_FACILITY
      case GET_FACILITY
      case UPDATE_FACILITY
      case DELETE_FACILITY

      /* STALLS */
      case CREATE_STALL
      case GET_STALL
      case UPDATE_STALL
      case DELETE_STALL

      /* POSTS */
      case CREATE_POST
      case GET_POST
          case UPDATE_POST
          case DELETE_POST

          case ADD_RESERVATION
          case REMOVE_RESERVATION

          case AUTHENTICATE
}

public class Message<T: Decodable> : Decodable {

    var type: MessageType?
    var model : T?
    init(type:MessageType,model:T) {
        self.type = type
        self.model = model
    }

Horse Model

     let id: Int?
     let name: String?
     let race: String?
     let lifeNumber : String?
     let chipNumber : String?
     let birthDate : Date?
     let gender : Gender?
     let medicalReports : [MedicalReport]?
     let owners : [User]?


 init (id:Int, name:String,race:String,lifeNumber: String, chipNumber:String, birthDate : Date, gender:Gender, medicalReports: [MedicalReport] , owners : [User]) {

      self.id = id
      self.name = name
      self.race = race
      self.lifeNumber = lifeNumber
      self.chipNumber = chipNumber
      self.birthDate = birthDate
      self.gender = gender


      self.medicalReports = medicalReports
      self.owners = owners

  }

Here is my JSON response:

{"type":"GET_HORSE","model":{"id":1,"name":"Horse2","race":"Race2","lifeNumber":"lifenumber2","chipNumber":"chipnumber2","birthDate":1579182813067,"gender":"MALE","medicalReports":[],"owners":[]}}

Here is the code

func getJSON (completion: @escaping (Message<Horse>)->()) {
        let url = "http://localhost:8083/horse/1"
    if let url = URL(string: url)
    {
        let task = session.dataTask(with: url) { data, response, error in

                  if error != nil || data == nil {
                      print("Client error!")
                      return
                  }
            let str = String(decoding: data!, as: UTF8.self)
            print(str)
                  do {
                   let decoder = JSONDecoder()
                   print("nothing")

                    if let json = try? decoder.decode(Message<Horse>.self, from: data!) {
                       print(json)
                       print("something")
                   }

                  } catch {
                      print("JSON error: \(error.localizedDescription)")
                  }
              }

              task.resume()
        print("finished")
    }

This is the error:

JSON error: The data couldn’t be read because it isn’t in the correct format
Esmee
  • 51
  • 8

1 Answers1

3

Your MessageType is an Int, but in the JSON it appears to be a string. It's possible you have a similar problem with your Gender type (which you didn't include here). Your birthDate field is a Date, but in the JSON it's an Int.

Go through your model and make sure it actually matches your JSON. Printing the error (rather than error.localizedDescription) should tell you exactly where it's having trouble. I recommend experimenting in a Playground with just the response JSON and the parser (getting rid of the networking code).

Rob Napier
  • 286,113
  • 34
  • 456
  • 610