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

Bra*_*ndt 6 json swift jsondecoder

在 Playgrounds 中,以下代码会产生错误:

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)
Run Code Online (Sandbox Code Playgroud)

致命错误:“尝试!” 表达式意外引发错误: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.",underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Unescaped control字符 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))

        }

      }
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 8

json在操场上的表示不正确。它是由带有 的字符串文字构造的\\n。但在字符串\xe2\x80\x99s 转换为Data. 但 JSON 字符串中不允许使用换行符。您需要两个单独的字符,即JSON 中的字符串中的\\后跟。n您可以通过使用\\另一个转义来做到这一点\\,例如:

\n\n
let json = """\n    {\n        "TextBody": "First Line\\\\n\\\\nLastLine"\n    }\n    """.data(using: .utf8)!\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,在 Swift 5 及更高版本中,您可以使用扩展字符串分隔符,例如:

\n\n
let json = #"""\n    {\n        "TextBody": "First Line\\n\\nLastLine"\n    }\n    """#.data(using: .utf8)!\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者:

\n\n
let json = #"{"TextBody": "First Line\\n\\nLastLine"}"#\n    .data(using: .utf8)!\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

如果您的 Web 服务返回的 JSON 的字符串0x0a值中包含换行符 ( ),而不是\\后跟字符,则 I\xe2\x80\x99d 会感到非常惊讶n字符,我\xe2\x80\x99d 会感到非常惊讶。只有当一些缺乏经验的后端开发人员手动构建 JSON 而不是使用正确执行此操作的函数时,才会发生这种情况。

\n\n

你说你\xe2\x80\x99\\n在邮递员中看到。这表明您的服务器响应是正确的,字符串中有两个字符,\\后跟, 。n例如,这里有一个 Web 服务,它回显了我的输入,并且该 JSON 格式良好,\\后跟n

\n\n

在此输入图像描述

\n\n

如果您的输出类似于上面的内容,那么您的 JSON 是有效的,并且上面代码片段中的问题仅仅是您如何在 Playground 中用 Swift 代码中的字符串文字表示此 JSON 的表现。

\n\n

您只需要担心,如果您"First line在此 Postman \xe2\x80\x9craw\xe2\x80\x9d 视图中看到一行并看到Lastline"下一行(可能没有 \\n)。

\n\n

最重要的是,我们应该忽略你的 Playground 中的错误。解析您的实际服务器响应(不要将 JSON 剪切并复制到代码中,或者至少在没有那些扩展字符串文字的情况下不要这样做)。重点关注解析实际服务器响应时出现的错误(如果有)。我敢打赌,如果您在实际的服务器响应上运行解析器,您将不会遇到此 \xe2\x80\x9cUnescaped control character\xe2\x80\x9d 错误。

\n