Swift JSONDecoder无法使用转义字符解码有效的JSON

时间:2019-09-04 23:19:36

标签: json swift jsondecoder

在操场上,以下代码会产生错误:

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))

        }

      }

1 个答案:

答案 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

enter image description here

如果您的输出类似于上面,那么您的JSON是有效的,并且上面代码段中的问题仅是您如何在操场上的Swift代码中以字符串文字形式表示此JSON的体现。

如果您在此邮递员“原始”视图中的一行上看到"First line,而在下一行上看到Lastline"(大概没有\ n),则只需担心。

最重要的是,我们应该忽略您操场上的错误。解析您的实际服务器响应(不将JSON剪切并复制到代码中,或者至少不没有那些扩展的字符串文字)。关注解析实际服务器响应时遇到的错误(如果有)。我敢打赌,如果您在实际的服务器响应上运行解析器,则不会收到此“ Unescaped控制字符”错误。