Swift JSON解析函数未返回Failure却崩溃,原因是什么?
问题:解析JSON函数遇无效输入崩溃,未返回错误结果
我编写了一个解析输入JSON的函数,设计目标是解析失败时返回友好错误,但遇到无效JSON时,应用直接在以下代码行崩溃:
let data = try? JSONSerialization.data(withJSONObject: result),
完整函数代码如下:
static func parseModel<Response: Decodable>(from response: Any?, with error: Error? = nil) -> Result<Response, Error> { guard let result = response, let data = try? JSONSerialization.data(withJSONObject: result), let model = try? JSONDecoder().decode(Response.self, from: data) else { return .failure(error ?? APIError.emptyResponse) } return .success(model) }
为何该函数未返回.failure(error ?? APIError.emptyResponse),反而直接崩溃?
原因及解决方案
崩溃原因
JSONSerialization.data(withJSONObject:) 方法的特殊行为导致了崩溃:当传入的对象不是JSON合法类型时,它不会抛出可被try?捕获的Error,而是直接触发运行时崩溃。try?仅能处理函数抛出的异常,无法拦截运行时崩溃,因此代码执行到这一行时直接终止,根本没机会进入guard的else分支返回错误结果。
常见的非法输入场景包括:传入NSNull、存在循环引用的对象、包含JSON不支持的类型(如未处理的Date实例、未遵循JSONSerialization要求的自定义类)等。
修复方案
核心思路是提前校验输入对象是否符合JSON序列化要求,避免触发崩溃:
static func parseModel<Response: Decodable>(from response: Any?, with error: Error? = nil) -> Result<Response, Error> { guard let result = response else { return .failure(error ?? APIError.emptyResponse) } // 先校验对象是否可被JSON序列化 guard JSONSerialization.isValidJSONObject(result), let data = try? JSONSerialization.data(withJSONObject: result), let model = try? JSONDecoder().decode(Response.self, from: data) else { // 建议新增APIError.invalidResponse类型,替代emptyResponse更精准 return .failure(error ?? APIError.invalidResponse) } return .success(model) }
额外优化建议:拆分guard条件,分别处理不同阶段的错误(如对象非法、序列化失败、解码失败),返回对应错误类型,便于后续排查问题。
内容的提问来源于stack exchange,提问作者Evgeniy Kleban
相关产品推荐
相关产品推荐

