Swift使用JSONSerialization转换字典时如何忽略不兼容类型避免异常
问题解决方法
JSONSerialization本身没有内置忽略不兼容类型的配置项,默认只要待序列化的对象中存在非JSON兼容类型(包括NSData、自定义类实例等),就会直接抛出异常,无法仅保留兼容值继续序列化。
你不需要手动遍历复杂的嵌套结构,只需写两个通用的递归扩展,就可以自动处理任意层级的字典、数组嵌套,过滤所有非兼容类型:
import Foundation extension Dictionary where Key == AnyHashable, Value == Any { /// 递归过滤所有非JSON兼容类型,返回可直接序列化的字典 func filteredForJSONSerialization() -> [AnyHashable: Any] { var validDict = [AnyHashable: Any]() for (key, value) in self { // 递归处理嵌套字典 if let subDict = value as? [AnyHashable: Any] { validDict[key] = subDict.filteredForJSONSerialization() } // 递归处理嵌套数组 else if let subArray = value as? [Any] { validDict[key] = subArray.filteredForJSONSerialization() } // 保留JSON兼容的基础类型 else if value is String || value is NSNumber || value is NSNull { validDict[key] = value } // NSData等非兼容类型直接跳过,不写入结果 } return validDict } } extension Array where Element == Any { /// 递归过滤数组中的非JSON兼容类型 func filteredForJSONSerialization() -> [Any] { compactMap { element in if let subDict = element as? [AnyHashable: Any] { return subDict.filteredForJSONSerialization() } else if let subArray = element as? [Any] { return subArray.filteredForJSONSerialization() } else if element is String || element is NSNumber || element is NSNull { return element } return nil } } }
使用时仅需要在序列化前调用一次扩展方法即可,不需要改动其他逻辑:
let validDictionary = inputDictionary.filteredForJSONSerialization() do { let jsonData = try JSONSerialization.data(withJSONObject: validDictionary, options: [.prettyPrinted]) // 后续处理JSON数据 } catch { // 此时仅会出现极端场景的报错,比如字典全为空等 print(error.localizedDescription) }
如果需要保留NSData的内容而非直接过滤,可以在判断逻辑中新增分支,将NSData转换为base64字符串后存入结果即可。
内容的提问来源于stack exchange,提问作者Mike Nathas
相关产品推荐
相关产品推荐

