Swift JSONDecoder无法使用转义字符解码有效的JSON [英] Swift JSONDecoder can't decode valid JSON with escape characters

查看:954
本文介绍了Swift JSONDecoder无法使用转义字符解码有效的JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In playgrounds, the following code produces an error:

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行

Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Unescaped control character around character 27." UserInfo={NSDebugDescription=Unescaped control character around character 27.}))): file MyPlayground.playground, line 19

根据JSONLint,上面的JSON完全有效.那有什么呢?

The JSON above is perfectly valid according to JSONLint. So what gives?

更新:

我需要一个可以处理从API返回的数据的解决方案.到目前为止,我想出了一些东西,但这很重要...

I need a solution that will handle data returned from an API. Here is something I came up with so far, but it's gross...

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

        }

      }

推荐答案

您在游乐场中的json表示不正确.它由其中包含\n的字符串文字构造而成.但这会在您的字符串中转换为Data之前替换掉换行符.但是JSON字符串中不允许使用换行符.您需要在JSON的字符串中使用两个单独的字符,即\后跟n.您可以通过用另一个\转义\来做到这一点,例如:

Your json in your playground is represented incorrectly. It is constructed from a string literal with the \n in it. But that is being replaced newline characters in your string before it’s converted to a Data. But a newline is not permitted within JSON string. You need the two separate characters, namely \ followed by n in your string within the JSON. You can do that by escaping the \ with another \, e.g.:

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

或者,或者,在Swift 5和更高版本中,您可以使用扩展的字符串定界符,例如:

Or, alternatively, in Swift 5 and later, you can use extended string delimiters, such as:

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

或者:

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


如果您的网络服务返回的JSON字符串值中包含换行符(0x0a),而不是\字符后跟n字符,我会感到非常惊讶.仅当某些经验不足的后端开发人员手动构建JSON而不是使用正确执行此功能的函数时,这种情况才会发生.


I’d be very surprised if your web service was returning a JSON with newline characters (0x0a) within its string values, rather than \ character followed by n character. That would only happen if some inexperienced back-end developer was manually building JSON rather than using functions that do this properly.

您说您在Postman中看到\n.这表明您的服务器响应是正确的,字符串中有两个字符,\后跟n.例如,这是一个Web服务,它回显了我的输入,并且此JSON的格式正确,其中\后跟n:

You say that you’re seeing \n in Postman. That suggests that your server response is correct, that there are two characters, \ followed by n, within the string. For example, here is a web service that echoed my input back and this JSON is well formed with \ followed by n:

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

If your output looks like the above, then your JSON is valid and the problem in your code snippet above is merely a manifestation of how you represented this JSON in a string literal in Swift code in your playground.

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

You only need to worry if you see "First line on one line in this Postman "raw" view and see Lastline" on the next line (presumably with no \n).

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

Bottom line, we should ignore the error in your playground. Parse your actual server response (not cutting-and-copying the JSON into code, or at least not without those extended string literals). Focus on what errors, if any, you get when you parse the actual server response. I wager that if you run your parser on your actual server response, you won’t get this "Unescaped control character" error.

这篇关于Swift JSONDecoder无法使用转义字符解码有效的JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆