从API调用返回的base64encoded字符串在运行Data(base64encoded:data)后显示nil

时间:2019-07-22 19:56:13

标签: ios swift base64 jsondecoder

我对此很困惑。我一直以为我的服务器出了点问题,但是经过测试,似乎使用Data(base64encoded:data)会产生nil,即使数据已经存在并且实际上是base64encoded。 我已经尝试了所有可以想到的方法,但没有任何效果。这是我正在使用的代码以及输出...

do {
  print("DATA as a string: ", String(data: data!, encoding: .utf8) ?? "NONE AVAILABLE")
  let decodedData = Data(base64encoded: data!, options: .ignoreUnknownCharacters)
  print("DECODED DATA: ")
  print(decodedData as Any)
  let apiResponse = try JSONDecoder().decode(ApiConnectionResponse.self, from: decodedData!)
  completion(.success(apiResponse))
} catch {
  completion(.failure(error))
}

输出是...

  

数据作为字符串:   eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0。

     

已解码数据:无

因此,字符串是合法的base64编码字符串,它会解码为

  

{“成功”:“假”,“错误”:“ mobile_pin_connect:无效或已过期”}

但是解码后的数据为零。我不明白,当字符串是base64编码的字符串而不是nil时,怎么可能为nil。 我什至尝试过像这样强制字符串在其中...

let decodedData = Data(base64encoded: String(data: data!, encoding: .utf8))

仍然没有运气。它引发了致命错误,我可以在Xcode底部的部分中看到数据实际上是“(Data?)92字节”。我无法弄清楚的是为什么在遍历Data()后它为nil( )...

任何帮助将不胜感激,我真的迷失了方向,无法弄清楚为什么我可以制作字符串,但不能制作数据。

这的最终结果是,我需要获取JSONDecoder()。decode来处理来自服务器的回复,如果可以弄清楚为什么在数据调用之后为什么它为零,我想我可以完成这部分工作。谢谢。

3 个答案:

答案 0 :(得分:2)

您需要检查数据长度,除以3,如果结果不为零,则向数据中添加一或两个字节。尝试这样:

let result = data.count % 3
let decodedData = Data(base64Encoded: data + .init(result == 0 ? [] : result == 1 ? [65] : [65,65]))

extension Data {
    var base64encodedDataPadded: Data {
        let data = last == 46 ? dropLast() : self
        let result = data.count % 3
        return data + .init(result == 0 ? [] : result == 1 ? [65] : [65,65])
    }
}

游乐场测试:

let data = Data("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0.".utf8)
let decodedData = Data(base64Encoded: data.base64encodedDataPadded)!
print(String(data: decodedData, encoding: .utf8)!) // "{"success":"false","error":"mobile_pin_connect: invalid or expired"}"

答案 1 :(得分:0)

我想编码的数据是错误的。

let originalString = """
{"success":"false","error":"mobile_pin_connect: invalid or expired"}
"""

let base64string = originalString.data(using: .utf8)?.base64EncodedString()
print(base64string)

let base64EncodedData = originalString.data(using: .utf8)?.base64EncodedData()
let base64EncodedString = String(data: base64EncodedData!, encoding: .utf8)
print(base64EncodedString)

let decodedData = Data(base64Encoded: base64EncodedData!)
let decodedString = String(data: decodedData!, encoding: .utf8)
print(decodedString)

日志如下:

Optional("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0=")
Optional("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0=")
Optional("{\"success\":\"false\",\"error\":\"mobile_pin_connect: invalid or expired\"}")

根据base64规范,.不是有效字符。 =是适合填充的字符。

https://en.wikipedia.org/wiki/Base64

答案 2 :(得分:0)

您显示的base64字符串末尾有句点和换行符。看起来不正确。在线base64解码器可以在有或没有最后一个句号和换行符的情况下对其进行解码,但是Swift可能会在适当的位置使它窒息。