【发布时间】:2019-08-12 13:16:47
【问题描述】:
我从 下面的示例代码中提到的 SO 套接字获取了一个真实的响应。我需要将其解码为某种类型的对象。所以我定义了两个可解码结构:SocketResponse 和Question。
然后我尝试使用默认的JSONDecoder 对其进行解码。
但由于 data 键包含大量无效的 json 格式,它无法正常工作并抛出此错误:
dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "给定的数据不是有效的 JSON。",underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840"没有字符串字符 2 周围对象中值的键。" UserInfo={NSDebugDescription=字符 2 周围对象中的值没有字符串键。})))
我也尝试了JSONSerialization,但它无法解码并引发类似错误。
那么我如何将这种类型的字符串解码为类型化对象而不丢失 HTML 格式?(因为响应可能不同,我们唯一可以传递的就是 data 值总是一个 String 包含一些 HTML 代码。)
- 游乐场:
这是您可以使用的简单重现代码:
struct SocketResponse<T: Decodable>: Decodable {
let action: String
let data: T
}
struct Question: Decodable {
let id: String
let body: String
let tags: [String]
let siteid: Int
let noAnswers: Bool
let hasBounty: Bool
let fetch: Bool
}
let responseData = """
{
"action": "1-questions-newest-tag-ios",
"data": "{"id":"57238686","body":"<div class=\"question-summary\" id=\"question-summary-57238686\">\r\n <div class=\"statscontainer\">\r\n <div class=\"stats\">\r\n <div class=\"vote\">\r\n <div class=\"votes\">\r\n <span class=\"vote-count-post \"><strong>0</strong></span>\r\n <div class=\"viewcount\">votes</div>\r\n </div>\r\n </div>\r\n <div class=\"status unanswered\">\r\n <strong>0</strong>answers\r\n </div>\r\n </div>\r\n <div class=\"views \" title=\"1 view\">\r\n 1 view\r\n</div>\r\n </div>\r\n <div class=\"summary\">\r\n <h3><a href=\"/questions/57238686/how-to-realize-a-movable-controller-in-ipados-like-mail-app-in-ipad\" class=\"question-hyperlink\">How to realize a movable controller in iPadOS, like mail APP in iPad</a></h3>\r\n <div class=\"excerpt\">\r\n Mail App in iPad, when we create a new mail, the controller will be presented. But in iPadOS system, this controller can be moved, and if move it to the left side or right side, it can become a ...\r\n </div>\r\n <div class=\"tags t-ios t-swift t-ipad t-ipados\">\r\n <a href=\"/questions/tagged/ios\" class=\"post-tag\" title=\"show questions tagged 'ios'\" rel=\"tag\">ios</a> <a href=\"/questions/tagged/swift\" class=\"post-tag\" title=\"show questions tagged 'swift'\" rel=\"tag\">swift</a> <a href=\"/questions/tagged/ipad\" class=\"post-tag\" title=\"show questions tagged 'ipad'\" rel=\"tag\">ipad</a> <a href=\"/questions/tagged/ipados\" class=\"post-tag\" title=\"show questions tagged 'ipados'\" rel=\"tag\">ipados</a> \r\n </div>\r\n <div class=\"started fr\">\r\n <div class=\"user-info \">\r\n <div class=\"user-action-time\">\r\n <a href=\"/questions/57238686/how-to-realize-a-movable-controller-in-ipados-like-mail-app-in-ipad\" class=\"started-link\">asked <span title=\"2019-07-28 07:08:46Z\" class=\"relativetime\">just now</span></a>\r\n </div>\r\n <div class=\"user-gravatar32\">\r\n <a href=\"/users/11847413/peipei\"><div class=\"gravatar-wrapper-32\"><img src=\"https://lh6.googleusercontent.com/-RJzULVcP1iM/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3reW_khZzpeiqEPv6Cww36Wohd_oUg/photo.jpg?sz=32\" alt=\"\" width=\"32\" height=\"32\"></div></a>\r\n </div>\r\n <div class=\"user-details\">\r\n <a href=\"/users/11847413/peipei\">peipei</a>\r\n <div class=\"-flair\">\r\n <span class=\"reputation-score\" title=\"reputation score \" dir=\"ltr\">1</span><span title=\"1 bronze badge\" aria-hidden=\"true\"><span class=\"badge3\"></span><span class=\"badgecount\">1</span></span><span class=\"v-visible-sr\">1 bronze badge</span>\r\n </div>\r\n </div>\r\n</div>\r\n </div>\r\n </div>\r\n</div>","tags":["ios","swift","ipad","ipados"],"siteid":1,"noAnswers":true,"hasBounty":false,"fetch":false}"
}
""".data(using: .utf8)!
do {
let json = try JSONDecoder().decode(SocketResponse<Question>.self, from: responseData)
print(json)
} catch {
print(error)
}
【问题讨论】:
-
action&data必须用引号括起来才能成为有效的 JSON。 -
data: "{"id":"57238686"json 在哪里开始和结束?! -
他们需要报价,但不足以成为有效的 json @Dementic
-
@Liam 在行尾
"fetch":false}" -
你还需要转义
"id":"57238686","body"
标签: html json swift nsjsonserialization decodable