【问题标题】:JSON/simple text parsing server response with Swift 4 Decodable使用 Swift 4 解码的 JSON/简单文本解析服务器响应
【发布时间】:2018-03-25 14:09:25
【问题描述】:
我遇到了以下问题。通过客户端 iOS 应用程序与发送 2 种类型响应的特定后端服务协作:成功时的 JSON 和错误时的简单文本。
对于 JSON,我有一个简单的可解码结构:
struct Response: Decodable {
let message: String
}
它一直有效,直到服务器在 http 正文中发送简单文本,我收到以下错误:
"Error Domain=NSCocoaErrorDomain Code=3840 "JSON 文本没有开始
带有数组或对象以及允许未设置片段的选项。”
也许 Response 结构在这种情况下可能更通用?
【问题讨论】:
标签:
json
swift
parsing
codable
【解决方案1】:
没有简单的方法可以让您的 Decodable 结构处理此类错误,因为如果您尝试解码的 Data 不是有效的 JSON,甚至不会调用 init(from decoder:) 方法,因此您需要处理初始化程序范围之外的错误。
一种可能的解决方案是处理JSONDecoder.decode(Response.self,from:) 方法的catch 块中的错误。一旦decode 函数抛出错误,您可以检查错误是否是由于输入不正确(在这种情况下很可能意味着输入是简单字符串而不是 JSON),您可以简单地将响应数据转换为String,然后调用Response的成员初始化器,用字符串响应对其进行初始化。
以下示例显示了如何使用两个示例响应来处理这种情况,一个是有效的 JSON,另一个是简单的字符串。
let validJsonResponseData = """
{"message" : "A message"}
""".data(using: .utf8)!
let simpleTextResponseData = "Error".data(using: .utf8)!
struct Response: Decodable {
let message: String
}
do {
let successResponse = try JSONDecoder().decode(Response.self, from: validJsonResponseData)
let errorResponse = try JSONDecoder().decode(Response.self, from: simpleTextResponseData)
} catch {
if let error = error as? DecodingError {
switch error {
case .dataCorrupted(_):
if let simpleTextResponse = String(data: simpleTextResponseData, encoding: .utf8) {
let errorResponse = Response(message: simpleTextResponse)
}
default:
throw error
}
} else {
throw error
}
}