无法从Alomafire正确解析JSON数据

7d7tgy0s  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(173)

我知道有各种各样的线索,但似乎有一个根本的缺陷,我对对象的理解在斯威夫特。
因此,我使用了以下函数,该函数将返回预期的JSON响应:

func executeGet( completion: @escaping ([[String:Any]]?, Error?) -> Void) {
                AF.request("https://myURL",
                           method:.get,
                           headers:headers).responseJSON{ response in
                    debugPrint(response) <- I get readable JSON response from here
                 
                    if let error = response.error {
                        completion(nil, error)
                    }
                    else if let jsonArray = response.value as? [[String:Any]]{
                        completion(jsonArray, nil)
                    }
                    else if let jsonDict = response.value as? [String:Any]{
                        completion([jsonDict], nil )
                    }
                    
                }
            }

然后,我可以利用完成处理程序读取AL作用域之外的JSON响应:

executeGet() { (json, error) in
                if let error = error{
                    print(error.localizedDescription)
                    
                }
                else if let json = json {
                    print(type(of:json)) <- did this for sanity check
                    print(json["result"][0]["capturedlists"]) <- Error No exact matches in call to subscript 
                }
            }

但是我不能只获取JSON的'capturedLists'部分,我需要捕获的JSON片段如下所示:

"capturedLists":{"Something":
    [{"Position":"1","A1":"a1","B1":"b1"},
    {"Position":"2","A2":"a2","B2":"b2"}]}}}

有人能帮我找出我做错了什么吗?我知道通常你可以通过类似于response[a][0]的方式从Json获取数据,但由于某种原因,它在这里不起作用。
编辑:Upone建议我使用Quicktype为我的响应获取一个结构体,并得到以下内容:

struct Welcome: Codable {
let statusCode: Int
let messageCode: String
let result: Result
 }

   // MARK: - Result
 struct Result: Codable {
let id: String
let inputParameters: InputParameters
let robotID: String
let runByUserID, runByTaskMonitorID: JSONNull?
let runByAPI: Bool
let createdAt, startedAt, finishedAt: Int
let userFriendlyError: JSONNull?
let triedRecordingVideo: Bool
let videoURL: String
let videoRemovedAt: Int
let retriedOriginalTaskID: String
let retriedByTaskID: JSONNull?
let capturedDataTemporaryURL: String
let capturedTexts: CapturedTexts
let capturedScreenshots: CapturedScreenshots
let capturedLists: CapturedLists

enum CodingKeys: String, CodingKey {
    case id, inputParameters
    case robotID = "robotId"
    case runByUserID = "runByUserId"
    case runByTaskMonitorID = "runByTaskMonitorId"
    case runByAPI, createdAt, startedAt, finishedAt, userFriendlyError, triedRecordingVideo
    case videoURL = "videoUrl"
    case videoRemovedAt
    case retriedOriginalTaskID = "retriedOriginalTaskId"
    case retriedByTaskID = "retriedByTaskId"
    case capturedDataTemporaryURL = "capturedDataTemporaryUrl"
    case capturedTexts, capturedScreenshots, capturedLists
}
 }
9cbw7uwe

9cbw7uwe1#

.responseJSON已弃用。请不要使用它。
发生错误的原因是json["result"]返回Any,但编译器必须知道后续索引订阅的静态类型。
由于您有Decodable型号,AF提供responseDecodable。将您的函数更改为

func executeGet( completion: @escaping (Result<Welcome,Error>) -> Void) {
            AF.request("https://myURL",
                       method:.get,
                       headers:headers).responseDecodable(of: Welcome.self) { response in

        switch response.result {
            case .success(let welcome): 
                completion(.success(welcome))

            case .failure(let error): 
                completion(.failure(error))
        }
    }

}

其甚至可以被简化为

func executeGet( completion: @escaping (Result<Welcome,Error>) -> Void) {
            AF.request("https://myURL",
                       method:.get,
                       headers:headers).responseDecodable(of: Welcome.self) { response in

        completion(response.result)
    }

}

然后称之为

executeGet() { result in
    switch result {
        case .success(let welcome): print(welcome)
        case .failure(let error): print(error)
    }
}

如果您得到一个错误,模型与JSON不匹配,错误会确切地告诉您出了什么问题

相关问题