Swift中URLSession返回Data的编码与JSON解析及字符串转换问题
Swift中JSON解码与字符编码处理问题解析
1. Data是否自带编码信息?
Data本质是原始字节的容器,不包含任何字符编码元数据。它只存储字节序列,完全不知道这些字节对应哪种字符编码(如UTF-8、GBK等)。
2. JSONDecoder#decode(…)是否会自动检测编码?
JSONDecoder的decode(_:from:)方法直接基于Data解析,不会自动检测字符编码。JSON规范默认要求使用UTF-8编码,但如果服务返回其他编码(如UTF-16、GBK)的Data,直接调用decode会抛出解码错误。
3. 如何利用URLResponse#textEncodingName创建对象?
URLResponse的textEncodingName会返回服务器指定的编码名称(如"utf-8"、"gb2312"),你可以先将Data转成对应编码的String,再转回UTF-8编码的Data,最后用JSONDecoder解析:
func decodeFromResponse<T: Decodable>(type: T.Type, data: Data, response: URLResponse) throws -> T { // 从响应获取编码,默认 fallback 到UTF-8 let encodingName = (response as? HTTPURLResponse)?.textEncodingName ?? "utf-8" guard let cfEncoding = CFStringConvertIANACharSetNameToEncoding(encodingName as CFString), let encoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(cfEncoding)) else { throw NSError(domain: "EncodingError", code: 0, userInfo: [NSLocalizedDescriptionKey: "不支持的编码格式"]) } // 转成对应编码的字符串,再转回UTF-8格式的Data guard let jsonString = String(data: data, encoding: encoding), let utf8Data = jsonString.data(using: .utf8) else { throw NSError(domain: "DataConversionError", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法将数据转换为UTF-8格式"]) } return try JSONDecoder().decode(type, from: utf8Data) }
4. 无URLResponse时,如何自动检测Data编码并转成String?
如果无法获取URLResponse,可以通过两种方式处理:
方法1:尝试常见编码
遍历主流字符编码,找到能正确解析Data的编码:
func convertDataToString(_ data: Data) -> String? { let commonEncodings: [String.Encoding] = [.utf8, .utf16, .utf16BigEndian, .utf16LittleEndian, .gbk, .isoLatin1] for encoding in commonEncodings { if let string = String(data: data, encoding: encoding) { return string } } return nil }
方法2:用Core Foundation自动检测编码
借助系统API自动识别字节流的编码,准确性更高:
func detectEncodingAndConvertToString(_ data: Data) -> String? { let cfData = data as CFData var detectedEncoding: CFStringEncoding = 0 let cfString = CFStringCreateFromExternalRepresentation(nil, cfData, &detectedEncoding) return cfString as String? }
内容的提问来源于stack exchange,提问作者XDR
相关产品推荐
相关产品推荐

