0

I am writing a Swift 5.x app using Alamofire 5 to get a list of files from an API I wrote. The API returns the file list as a JSON Data object. I want to then get this data into a struct I created. I am not able to get this working. Here is an example JSON string that my server sends over when you hit the API endpoint:

[{
    "ID": "0d37ee7a-39bf-4eca-b3ec-b3fe840500b5",
    "Name": "File01.iso",
    "Size": 6148
}, {
    "ID": "656e0396-257d-4604-a85c-bdd0593290cd",
    "Name": "File02.iso",
    "Size": 224917843
}, {
    "ID": "275fdf66-3584-4899-8fac-ee387afc2044",
    "Name": "File04.iso",
    "Size": 5549504
}, {
    "ID": "1c73f857-56b5-475b-afe4-955c9d2d87fe",
    "Name": "File05.iso",
    "Size": 15476866871
}, {
    "ID": "bfebbca2-49de-43d7-b5d0-3461b4793b62",
    "Name": "File06.iso",
    "Size": 37254264
}]

I created the following Data Model in swift to hold this:

struct Files: Decodable {
    let root: [File]
}

struct File: Decodable, Identifiable {
    var id: UUID
    var name: String
    var size: Int
}

enum CodingKeys: String, CodingKey {
    case id = "ID"
    case name = "Name"
    case size = "Size"
}

Then I used Alamofire 5.x to call the API endpoint and attempt to decode the JSON and place it into the object in question:

func getPackageFilesJSON() {
    AF.request("http://localhost:8080/api/v1/list/pkgs").responseDecodable(of: Files.self) { response in
        guard let serverFiles = response.value else {
            print("Error Decoding JSON")
            return
        }
        let self.serverFilesList = serverFiles
    }
}

This fails. If I debugPrint the response I get this for the result:

[Result]: failure(Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: 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)))))

I have never been great at creating these data models and decoding JSON into them. I am sure I am missing something silly. I am hopeful that someone more knowledgable than me, or a second set of eyes can help me get this working.

Thanks, Ed

1 Answer 1

2

There is no key root in the JSON. The root object is an array

Delete

struct Files: Decodable {
   let root: [File]
}  

and decode

AF.request("http://localhost:8080/api/v1/list/pkgs").responseDecodable(of: [File].self) { response in ...

and move the CodingKeys enum into the File struct

struct File: Decodable, Identifiable {
    var id: UUID
    var name: String
    var size: Int
    
    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case name = "Name"
        case size = "Size"
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Then I get failure(Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "id", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"id\", intValue: nil) (\"id\").", underlyingError: nil)))))
The CodingKeys enum must be inside the struct File
Moving the enum inside the struct did it. I originally did not have the Files struct but added it when it wasn't working. Glad my first instinct was right and that it was a simple coding issue. I will mark this as excepted.
I recommend to learn to read the DecodingError messages. They are extremely descriptive.

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.