iOS Swift中服务器返回JSON字符串无法转数组问题求助
排查Swift中AFNetworking返回JSON转数组失败的问题
从你的描述和代码来看,明明服务器返回的JSON字符串看起来和硬编码的一样,但转数组失败,这种情况通常是字符串转换过程中引入了隐藏问题或者服务器返回的格式和你以为的不一样,我来帮你一步步排查:
可能的原因1:字符串转Data时引入了隐藏字符(比如UTF-8 BOM)
你现在的代码是把服务器返回的原始Data先转成String,再转回Data来解析,这个过程很可能引入了额外的隐藏字符,比如UTF-8的字节顺序标记(BOM,\uFEFF)。服务器返回的原始Data可能带BOM,转成String时BOM会被保留,再转回Data后,JSON解析器会把这个BOM当成无效字符,导致解析失败,而你硬编码的字符串是没有这个BOM的,所以能成功。
解决方案:直接使用原始Data解析
跳过字符串转换的步骤,直接用服务器返回的原始Data来解析:
manager.get(urlString as String, parameters: params, progress: nil, success: { (operation, responseObject) in self.stopAnimation() guard let data = responseObject as? Data else { print("无效的返回数据") return } // 可选:移除可能存在的UTF-8 BOM var cleanData = data if cleanData.starts(with: Data([0xEF, 0xBB, 0xBF])) { cleanData = cleanData.dropFirst(3) } do { if let jsonArray = try JSONSerialization.jsonObject(with: cleanData, options: .allowFragments) as? [[String: Any]] { print(jsonArray) } else { print("返回数据不是预期的数组格式") } } catch { print("解析失败:\(error)") } }, failure: { (operation, error) in self.stopAnimation() print(error) self.alert(message: error.localizedDescription) })
可能的原因2:服务器返回的是“字符串包裹的JSON”
你打印的jsonstring是带外层双引号的:"[{\"propertyId\":\"1\",...}]",这说明服务器返回的不是直接的JSON数组,而是一个被双引号包裹的字符串。当你硬编码的时候,可能不小心去掉了外层的双引号,所以能成功解析,而服务器返回的字符串带着外层引号,解析时会被当成普通字符串,不是JSON数组。
解决方案:去除外层引号后再解析
如果确实是这种情况,你可以先把字符串首尾的双引号去掉,再转成Data解析:
manager.get(urlString as String, parameters: params, progress: nil, success: { (operation, responseObject) in self.stopAnimation() guard let data = responseObject as? Data, let jsonstring = String(data: data, encoding: .utf8) else { print("无效的返回数据") return } // 去除首尾的双引号 let trimmedString = jsonstring.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) guard let trimmedData = trimmedString.data(using: .utf8) else { print("字符串转Data失败") return } do { if let jsonArray = try JSONSerialization.jsonObject(with: trimmedData, options: .allowFragments) as? [[String: Any]] { print(jsonArray) } else { print("返回数据不是预期的数组格式") } } catch { print("解析失败:\(error)") } }, failure: { (operation, error) in self.stopAnimation() print(error) self.alert(message: error.localizedDescription) })
更简洁的方案:直接用AFJSONResponseSerializer
其实AFNetworking自带JSON解析的序列化器,你不需要手动转字符串和Data,直接设置responseSerializer为AFJSONResponseSerializer,框架会自动帮你完成解析:
let manager = AFHTTPSessionManager() manager.requestSerializer = AFJSONRequestSerializer() // 替换成JSON序列化器 manager.responseSerializer = AFJSONResponseSerializer() manager.responseSerializer.acceptableContentTypes = ["text/plain", "text/html", "application/json"] manager.requestSerializer.setValue("", forHTTPHeaderField: "apptoken") manager.requestSerializer.setValue(strAppToken, forHTTPHeaderField: "token") let urlString = "\(ApiConstantFile().baseUrlProperty)\(ApiConstantFile().getTemplateDataUrl)" print(urlString) manager.get(urlString, parameters: params, progress: nil, success: { (operation, responseObject) in self.stopAnimation() // 直接尝试转成数组 if let jsonArray = responseObject as? [[String: Any]] { print(jsonArray) } else { print("返回数据不是预期的数组格式") } }, failure: { (operation, error) in self.stopAnimation() print(error) self.alert(message: error.localizedDescription) })
这种方式能避免很多手动转换带来的问题,推荐优先尝试。
内容的提问来源于stack exchange,提问作者B.Saravana Kumar
相关产品推荐
相关产品推荐

