Swift 4中如何解析混合数组及提取字典指定属性?
解析JSON数组中的字典字段为String类型变量
嘿,我来帮你搞定这个JSON解析的问题!既然你已经用JSONSerialization把服务器响应转成了数组,接下来就一步步把字典里的指定字段解析成String类型变量吧~
第一步:确认数组结构
首先,假设你已经把服务器返回的Data转成了[[String: Any]]类型的数组(也就是数组里每个元素都是[String: Any]字典),代码大概是这样:
do { guard let responseArray = try JSONSerialization.jsonObject(with: serverResponseData, options: []) as? [[String: Any]] else { // 处理解析失败的情况,比如打印错误提示 print("JSON解析失败,不是预期的数组结构") return } // 接下来遍历数组解析每个字典 } catch { print("JSON序列化错误:\(error.localizedDescription)") }
第二步:逐个解析字段为String
对于每个字典里的字段,我们需要处理两种常见情况:字段本身就是String类型,或者字段是数字类型(比如NSNumber)需要转成String,同时还要处理字段为nil的情况(避免崩溃)。
单个字段解析示例
以cedula为例,我们可以这样写:
// 先尝试转成String,失败的话看看是不是NSNumber再转成String,都不行就用空字符串兜底 let cedula = item["cedula"] as? String ?? (item["cedula"] as? NSNumber)?.stringValue ?? ""
按照这个逻辑,把你需要的所有字段都处理一遍:
for item in responseArray { let cedula = item["cedula"] as? String ?? (item["cedula"] as? NSNumber)?.stringValue ?? "" let codZona = item["codZona"] as? String ?? (item["codZona"] as? NSNumber)?.stringValue ?? "" let departamento = item["departamento"] as? String ?? "" let dirección = item["dirección"] as? String ?? "" let fecing = item["fecing"] as? String ?? "" let mesa = item["mesa"] as? String ?? (item["mesa"] as? NSNumber)?.stringValue ?? "" let municipio = item["municipio"] as? String ?? "" let puesto = item["puesto"] as? String ?? "" // 这里可以把解析好的变量用起来,比如存到数组里或者做后续逻辑 }
更规范的方式:封装成结构体
如果需要频繁使用这些数据,建议把解析逻辑封装成一个结构体,这样代码更清晰,也方便维护:
struct LocationInfo { let cedula: String let codZona: String let departamento: String let dirección: String let fecing: String let mesa: String let municipio: String let puesto: String // 从字典初始化的方法,失败返回nil init?(from dictionary: [String: Any]) { // 解析每个字段,确保非空(如果允许空值,可以把属性改成可选类型String?) guard let cedula = dictionary["cedula"] as? String ?? (dictionary["cedula"] as? NSNumber)?.stringValue, let codZona = dictionary["codZona"] as? String ?? (dictionary["codZona"] as? NSNumber)?.stringValue, let departamento = dictionary["departamento"] as? String, let dirección = dictionary["dirección"] as? String, let fecing = dictionary["fecing"] as? String, let mesa = dictionary["mesa"] as? String ?? (dictionary["mesa"] as? NSNumber)?.stringValue, let municipio = dictionary["municipio"] as? String, let puesto = dictionary["puesto"] as? String else { print("某个字段解析失败,跳过该条目") return nil } self.cedula = cedula self.codZona = codZona self.departamento = departamento self.dirección = dirección self.fecing = fecing self.mesa = mesa self.municipio = municipio self.puesto = puesto } }
然后使用的时候,直接把数组转成结构体数组:
let locationInfos = responseArray.compactMap { LocationInfo(from: $0) } // locationInfos就是解析好的[LocationInfo]数组,直接用属性访问即可,比如locationInfos[0].cedula
几个注意点
- 字段名拼写要准确:比如
dirección带重音符号,一定要和服务器返回的key完全一致,不然会解析出nil。 - 空值处理:如果服务器可能返回nil,你可以选择用空字符串兜底,或者把结构体属性改成可选类型
String?,根据业务需求来。 - 数字转String:像
cedula、mesa这类可能是数字类型返回的字段,必须处理NSNumber转String的情况,否则直接转String会得到nil。
内容的提问来源于stack exchange,提问作者Orlando Combita
相关产品推荐
相关产品推荐

