在操场上,以下代码会产生错误:
import Foundation
struct Model: Codable {
let textBody: String
enum CodingKeys: String, CodingKey {
case textBody = "TextBody"
}
}
let json = """
{
"TextBody": "First Line\n\nLastLine"
}
""".data(using: .utf8)!
let model = try! JSONDecoder().decode(Model.self, from: json)
致命错误:“尝试!”表达式意外引发错误:Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath:[],debugDescription:“给定的数据不是有效的JSON。”,底层错误:可选(错误域= NSCocoaErrorDomain代码= 3840“未转义的控件字符27附近的字符。“ UserInfo = {NSDebugDescription =字符27附近的转义控制字符。})))):文件MyPlayground.playground,第19行
根据JSONLint,上述JSON完全有效。那有什么呢?
更新:
我需要一个可以处理从API返回的数据的解决方案。到目前为止,我想出了一些东西,但这很重要...
if let data = data,
let dataStr = String(data: data, encoding: .utf8),
let cleanData = dataStr.replacingOccurrences(of: "\n", with: "", options: .regularExpression).data(using: .utf8)
{
do {
let response = try JSONDecoder().decode(T.Response.self, from: cleanData)
completion(.success(response))
} catch (let error) {
print(error.localizedDescription)
completion(.failure(ApiError.decoding))
}
}
答案 0 :(得分:0)
您在操场上的json
表示不正确。它由其中包含\n
的字符串文字构造而成。但这已被替换为字符串中的换行符,然后转换为Data
。但是,JSON字符串中不允许使用换行符。您需要在JSON的字符串中使用两个单独的字符,即\
后跟n
。您可以通过用另一个\
转义\
来做到这一点,例如:
let json = """
{
"TextBody": "First Line\\n\\nLastLine"
}
""".data(using: .utf8)!
或者,或者,在Swift 5和更高版本中,您可以使用扩展的字符串定界符,例如:
let json = #"""
{
"TextBody": "First Line\n\nLastLine"
}
"""#.data(using: .utf8)!
或者:
let json = #"{"TextBody": "First Line\n\nLastLine"}"#
.data(using: .utf8)!
如果您的Web服务返回的JSON字符串值中包含换行符(0x0a
),而不是\
字符后跟n
字符,我会感到非常惊讶。仅当某些经验不足的后端开发人员手动构建JSON而不是使用正确执行此功能的函数时,这种情况才会发生。
您说您在Postman中看到\n
。这表明您的服务器响应是正确的,字符串中有两个字符,\
后跟n
。例如,这是一个Web服务,它回显了我的输入,并且此JSON的格式正确,其中\
后跟n
:
如果您的输出类似于上面,那么您的JSON是有效的,并且上面代码段中的问题仅是您如何在操场上的Swift代码中以字符串文字形式表示此JSON的体现。
如果您在此邮递员“原始”视图中的一行上看到"First line
,而在下一行上看到Lastline"
(大概没有\ n),则只需担心。
最重要的是,我们应该忽略您操场上的错误。解析您的实际服务器响应(不将JSON剪切并复制到代码中,或者至少不没有那些扩展的字符串文字)。关注解析实际服务器响应时遇到的错误(如果有)。我敢打赌,如果您在实际的服务器响应上运行解析器,则不会收到此“ Unescaped控制字符”错误。