Home > Blockchain >  How to decodable request from Laravel in Swift and Alamofire
How to decodable request from Laravel in Swift and Alamofire

Time:01-16

I have a problem about decodable the "product" from laravel api request. Error is "The data couldn´t be read because it isn´t in the correct format.

request with insomnia is right and i get the product where the ean number has.

Laravel for database:

Schema::create('products', function (Blueprint $table) {
        $table->id();
        $table->bigInteger('ean');
        $table->string('name');
        $table->string('manufacturer');
        $table->string('productNumber');
        $table->longText('description')->nullable();
        $table->string('propertie')->nullable();
        $table->string('storagePlace');
        $table->integer('inStock')->nullable();
        $table->integer('unit');
        $table->longText('note')->nullable();
        $table->string('department')->default("zvk");
        $table->timestamps();

Swift Product decodable:

class Product: Decodable {

var id: Int
var ean: Double
var name: String
var manufacturer: String
var productNumber: String
var description: String
var propertie: String
var storagePlace: String
var inStock: Int
var unit: Int
var note: String
var department: String
var created_at: Date
var updated_at: Date

enum CodingKeys: String, CodingKey {

    case id
    case ean
    case name
    case manufacturer
    case productNumber
    case description
    case propertie
    case storagePlace
    case inStock
    case unit
    case note
    case department
    case created_at
    case updated_at
}

public required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.id = try container.decode(Int.self, forKey: .id)
    self.ean = try container.decode(Double.self, forKey: .ean)
    self.name = try container.decode(String.self, forKey: .name)
    self.manufacturer = try container.decode(String.self, forKey: .manufacturer)
    self.productNumber = try container.decode(String.self, forKey: .productNumber)
    self.description = try container.decode(String.self, forKey: .description)
    self.propertie = try container.decode(String.self, forKey: .propertie)
    self.storagePlace = try container.decode(String.self, forKey: .storagePlace)
    self.inStock = try container.decode(Int.self, forKey: .inStock)
    self.unit = try container.decode(Int.self, forKey: .unit)
    self.note = try container.decode(String.self, forKey: .note)
    self.department = try container.decode(String.self, forKey: .department)
    self.created_at = try container.decode(Date.self, forKey: .created_at)
    self.updated_at = try container.decode(Date.self, forKey: .updated_at)
}

}

Swift short code:

AF.request(productWithEanUrlRequest, method: .get, parameters: parameters, headers: headers).responseJSON { response in
        ProgressHUD.dismiss()
        
        //Gets HTTP status code
        let statusCode = (response.response?.statusCode)
        
        switch statusCode {
        case 200:
            //OK
            do {
                let product = try JSONDecoder().decode([Product].self, from: response.data!)
                debugPrint(product)
            } catch let error as NSError {
                AlertView.showAlertView(with: "Error", and: error.localizedDescription, in: self)
            }

Preview from request:

{
"product": [
    {
        "id": 1,
        "ean": "1234567890",
        "name": "Name",
        "manufacturer": "Hersteller",
        "productNumber": "Artikel-Nr.",
        "description": "Beschreibung vom Artikel",
        "propertie": "Eigenschaften",
        "storagePlace": "Lagerplatz",
        "inStock": "12",
        "unit": "0",
        "note": "Irgendwelche Notiz",
        "department": "zvs",
        "created_at": "2022-01-12T10:20:51.000000Z",
        "updated_at": "2022-01-12T10:20:51.000000Z"
    }
]

i can´t see the error i made!?

CodePudding user response:

Is there a chance you haven't set Accept header? From what I understand, you are expecting a json response, but it says something like : response is invalid format. I would suggest you try to use accept header in you request. Essentially something like:

headers: {
    "Accept": "application/json"
}

Of course convert the syntax as per the language you're using.

CodePudding user response:

my http headers look like this:

let headers: HTTPHeaders = [
        .authorization(bearerToken: userDefaults.string(forKey: "access_token")!),
        .accept("application/json")
    ]

CodePudding user response:

I sending the found product in laravel like this:

$product = Product::where('ean', $request['ean'])->get();
return response()->json([
        'product' => $product
    ]);

I have try to change the typ of class Product in swift:

class Product: Decodable, Identifiable {

var id: Int
var ean: Double
var name: String
var manufacturer: String
var productNumber: String
var description: String
var propertie: String
var storagePlace: String
var inStock: Int
var unit: Int
var note: String
var department: String
var created_at: Date
var updated_at: Date

enum CodingKeys: String, CodingKey {

    case id
    case ean
    case name
    case manufacturer
    case productNumber
    case description
    case propertie
    case storagePlace
    case inStock
    case unit
    case note
    case department
    case created_at
    case updated_at
}

public required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.id = try container.decode(Int.self, forKey: .id)
    self.ean = try container.decode(Double.self, forKey: .ean)
    self.name = try container.decode(String.self, forKey: .name)
    self.manufacturer = try container.decode(String.self, forKey: .manufacturer)
    self.productNumber = try container.decode(String.self, forKey: .productNumber)
    self.description = try container.decode(String.self, forKey: .description)
    self.propertie = try container.decode(String.self, forKey: .propertie)
    self.storagePlace = try container.decode(String.self, forKey: .storagePlace)
    self.inStock = try container.decode(Int.self, forKey: .inStock)
    self.unit = try container.decode(Int.self, forKey: .unit)
    self.note = try container.decode(String.self, forKey: .note)
    self.department = try container.decode(String.self, forKey: .department)
    self.created_at = try container.decode(Date.self, forKey: .created_at)
    self.updated_at = try container.decode(Date.self, forKey: .updated_at)
}

I print a debug from error.debugDescription in the terminal:

Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: \"Expected to decode Array<Any> but found a dictionary instead.\", underlyingError: nil))

I understand the error like this: You decode an array but you have a dictionary. But i sending from laravel a json and decode a json.

  •  Tags:  
  • Related