【问题标题】:Issue Parsing / Decoding JSON from API Endpoint Into Struct Object从 API 端点解析/解码 JSON 到结构对象的问题
【发布时间】:2021-04-15 04:51:12
【问题描述】:

我正在使用 Alamofire 5 编写一个 Swift 5.x 应用程序,以从我编写的 API 中获取文件列表。 API 将文件列表作为 JSON 数据对象返回。然后我想将这些数据放入我创建的结构中。我无法让这个工作。这是我的服务器在您点击 API 端点时发送的示例 JSON 字符串:

[{
    "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
}]

我迅速创建了以下数据模型来保存它:

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"
}

然后我使用 Alamofire 5.x 调用 API 端点并尝试解码 JSON 并将其放入有问题的对象中:

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
    }
}

这失败了。如果我调试打印响应,我会得到以下结果:

[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)))))

我从来都不擅长创建这些数据模型并将 JSON 解码为它们。我确定我错过了一些愚蠢的东西。我希望比我更博学的人,或者第二双眼睛可以帮助我完成这项工作。

谢谢, 埃德

【问题讨论】:

    标签: json swift request alamofire decodable


    【解决方案1】:

    JSON 中没有键 rootroot 对象是一个数组

    删除

    struct Files: Decodable {
       let root: [File]
    }  
    
    罢工>

    解码

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

    并将CodingKeys 枚举移动到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"
        }
    }
    

    【讨论】:

    • 然后我得到了失败(Alamofire.AFError.responseSerializationFailed(原因:Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(错误: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 \").", 底层错误:nil)))))
    • CodingKeys 枚举必须在 inside 结构 File
    • 将枚举移动到结构中就可以了。我最初没有 Files 结构,但在它不起作用时添加了它。很高兴我的第一直觉是正确的,这是一个简单的编码问题。我会将其标记为例外。
    • 我建议学习阅读DecodingError 消息。它们非常具有描述性。
    猜你喜欢
    • 2018-07-18
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2018-08-06
    相关资源
    最近更新 更多