ios - 如何忽略导致 Alamofire 响应序列化失败的“坏”字符?
问题描述
在 20 年的开发中,我总是通过在线搜索,特别是在 Stackoverflow 上找到我开发问题的所有答案。但这一次,为了我的生活,我无法找到解决方案:我正在开发一个 iOS 应用程序,它使用公共 api 来搜索公共交通的时间表。一切正常,尤其是安卓版本。但在 iOS 中,如果响应包含无效字符,则序列化过程会失败。
我正在使用 Alamofire 5.2.1、Swift 5、Xcode 11.5,API 是 Mentz 的 DIVA/EFA 服务,主要用于中欧(我认为)公共交通。
导致序列化失败的“坏”字符来自我想的编码问题,返回的 JSON 包含两个键
"opPublicCode":"�BB"
和
"operator":"ÖBB"
(冗余是这里的另一个问题,但没关系)。如您所见,这个德语 Ö 曾经正确表示,但一次不正确。正是这个单个字符导致 Alamofire 生成以下错误:
responseSerializationFailed(
reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed
(error: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [],
debugDescription: \"The given data was not valid JSON.\",
underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 \"Unable to convert data to string around character 7100.\"
UserInfo={NSDebugDescription=Unable to convert data to string around character 7100.})))))
这是调用api的代码,我觉得没什么特别的:
AF.request(url)
.responseDecodable(of: StaResponse.self) {(response: DataResponse<StaResponse, AFError> ) in
switch response.result {
case .success(let value):
callback(value, nil)
case .failure(let error):
callback(nil, error)
}
}
这是 Codable 对象(我通过将它设置为 nil 来忽略“opPublicCode”的有问题的值,因为我不需要它):
struct StaDiva : Codable {
let branch : String?
let dir : String?
let line : String?
let network : String?
let opCode : String?
let operatorName : String?
let opPublicCode : String? = nil
let project : String?
let stateless : String?
let supplement : String?
let tripCode : String?
enum CodingKeys: String, CodingKey {
case branch = "branch"
case dir = "dir"
case line = "line"
case network = "network"
case opCode = "opCode"
case operatorName = "operator"
case project = "project"
case stateless = "stateless"
case supplement = "supplement"
case tripCode = "tripCode"
}
}
我已经尝试了数千种方法,但都没有奏效。我设置了标题(Content-Encoding、Accept-Encoding、Accept),我尝试使用 Alamofire 4,在我的 Alamofire 请求中使用 .responseJSON 和 .responseString 而不是 .responseDecodable。我在 Codable 结构中尝试了几个选项,删除了“opPublicCode”字段,将其设置为 Data 或 Any 而不是 String。但没有运气。每次响应包含此运算符(火车的,ÖBB)的结果时,它都会失败。
我能在这里做什么?有没有办法忽略这个字符,也许通过替换它?我在使用 Alamofire 时错过了什么吗?或者有没有办法在 Codable 结构中解决这个问题(但我不这么认为,因为在尝试解码之前就发生了失败)。
不用说,试图让某人对 API 进行一些更改不是一种选择。
如果您需要更多信息,我当然可以提供更多详细信息。任何帮助将非常感激!提前致谢!
解决方案
使用 Alamofire 5.2,您可以使用 Alamofire 的DataPreprocessor
协议在被responseDecodable
. DataPreprocessor
有一个要求,func preprocess(_ data: Data) throws -> Data
您可以实施它来修复您的Data
. 所以你会实现这样的事情:
struct RepairPreprocessor: DataPreprocessor {
func preprocess(_ data: Data) throws -> Data {
// Find and remove or replace bad Data.
}
}
然后你可以使用它responseDecodable
:
.request(...)
.responseDecodable(of: SomeType.self, dataPreprocessor: RepairPreprocessor()) { response in
// Handle response.
}
这项工作是异步执行的,但鉴于您的响应的明显大小,您需要认识到这种Data
解析可能对性能产生的影响。我建议将其作为 raw 操作Data
,不String
进行转换,以获得更好的性能。
此外,您应该向后端供应商报告错误,说明他们的响应编码错误。它必须是 UTF-8 才能正确解析。
推荐阅读
- html - 以最少的重复条件渲染组件(ltr 到 rtl)中的东西?
- node.js - 如何将 worker_thread 依赖项与 webpack 捆绑
- rest - Destiny2 用户的 Bungie API:通过平台昵称查找 memberId 或 bungie 显示名称
- java - 从网络活动中获取特定文件
- android - Android 深度链接与导航图错误
- reactjs - 我正在尝试制作迪士尼加克隆,但我遇到了一个错误,上面写着
- postgresql - 在春季批处理中获取 HQL 查询中的 UTC 时间
- flutter - 我该如何解决“应该只有一项具有 [DropdownButton] 的值:null。” 颤振中的错误?
- objective-c - 添加跟踪区域时向实例发送无法识别的选择器
- iis - MVC5 控制器 (POST) 被调用两次(每周一次)