[NSJSONSerialization dataWithJSONObject:options:error:]:JSON 写入中的顶级类型无效

问题描述 投票:0回答:1

当我运行代码时,出现错误 ---------------------- “[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON 写入”。 ----------------------

class BaseAPI<T: TargetType> {
    
    func fetchData<M: Decodable>(target: T, responseClass: M.Type, completion:@escaping(Result<M?, NSError>) -> Void) {
        let method = Alamofire.HTTPMethod(rawValue: target.methods.rawValue)
        let headers = Alamofire.HTTPHeaders(target.headers ?? [:])
        let params = buildParams(task: target.task)
        AF.request(target.baseUrl + target.path, method: method, parameters: params.0, encoding: params.1, headers: headers).responseDecodable(of: M.self) { response in
            guard let statusCode = response.response?.statusCode else {
                //ADD Custom Error
                completion(.failure(NSError()))
                return
            }
            if statusCode == 200 {
                // Successful Request
                guard let jsonResponse = try? response.result.get() else {
                    completion(.failure(NSError()))
                    return
                }
                guard let theJSONData = try? JSONSerialization.data(withJSONObject: jsonResponse, options: []) else {
                    completion(.failure(NSError()))
                    return
                }
                guard let responseObj = try? JSONDecoder().decode(M.self, from: theJSONData) else {
                    completion(.failure(NSError()))
                    return
                }
                completion(.success(responseObj))
                
            } else {
                completion(.failure(NSError()))
            }
        }
        
        
    }
    
    private func buildParams(task: Task) -> ([String:Any], ParameterEncoding) {
        switch task {
            
        case .requestPlain:
            return ([:], URLEncoding.default)
        case .requestParameters(parameters: let parameters, encoding: let encoding):
            return (parameters, encoding)
        }
    }
}

而不是

try? JSONSerialization.data(withJSONObject: jsonResponse, options: [])
当我尝试
try? JSONSerialization.data(withJSONObject: jsonResponse, options: [])
代码时,它给出错误
No exact matches in call to class method 'jsonObject'

ios swift alamofire nsjsonserialization
1个回答
0
投票

回答你的问题,

jsonResponse
已经是解码的对象,
M
。无法使用任意对象调用
JSONSerialization
方法
data(withJSONObject:options:)
。它仅适用于非常特定的类型。 (请参阅
JSONSerialization
文档中可接受的类型列表。)这就是您收到此错误的原因。

话虽如此,这就引出了一个问题,为什么有人会尝试用

Data
将对象重新编码回
JSONSerialization
,并用
Data
JSONDecoder
重新解码回
M
。我建议消除这个,将代码简化为:

func fetchData<M: Decodable>(target: T, responseClass: M.Type = M.self, completion: @escaping(Result<M, Error>) -> Void) {
    let method = Alamofire.HTTPMethod(rawValue: target.methods.rawValue)
    let headers = Alamofire.HTTPHeaders(target.headers ?? [:])
    let params = buildParams(task: target.task)
    AF.request(target.baseUrl + target.path, method: method, parameters: params.0, encoding: params.1, headers: headers)
        .validate()
        .responseDecodable(of: M.self) { response in
            switch response.result {
            case .success(let value): completion(.success(value))
            case .failure(let error): completion(.failure(error))
            }
        }
}

一些观察:

  1. 作为一个小的改进,我建议将

    responseClass
    作为可选参数(通常可以从上下文推断出类型)。但我保留了编译器无法自动推断类型的情况下的参数)。

  2. 我还使用

    validate
    来检查状态代码。您不需要自己手动检查。

  3. 另请注意,在简化过程中,我已经不再使用

    try?
    try?
    是一种反模式,因为它会丢弃有意义的诊断信息。

    始终传递有意义的错误。如果调用者不关心详细信息,它可以根据需要忽略错误的详细信息。但在您确实存在解析错误的情况下,了解详细信息非常有用(这样您就知道哪个字段导致了问题)。

© www.soinside.com 2019 - 2024. All rights reserved.