序列化包含转义(反斜杠和双引号)的 JSON 字符串 Swift 返回格式错误的对象
Posted
技术标签:
【中文标题】序列化包含转义(反斜杠和双引号)的 JSON 字符串 Swift 返回格式错误的对象【英文标题】:Serialize JSON string that contains escaped (backslash and double quote) Swift return Badly formed object 【发布时间】:2018-10-26 04:36:56 【问题描述】:我有来自后端的响应字符串,如下所示:
"status": "success",
"data": "\"name\":\"asd\",\"address\":\"Street 1st\""
我认为问题是因为数据字符串中的双引号(“)。当我删除双引号时,序列化成功。但是响应来自后端,我必须处理它。
谁能解决这个问题?
谢谢。
这里是操场代码。
import Foundation
var jsonStr = """
"status": "success",
"data": "\"name\":\"asd\",\"address\":\"Street 1st\""
"""
let data = jsonStr.data(using: .utf8)
if let d = data
do
let o = try JSONSerialization.jsonObject(with: d)
print(o)
catch let e
print(e)
else
print("DATA conversion ERROR")
【问题讨论】:
【参考方案1】:首先,如果您将 JSON 包装在 Swift 4 的文字字符串语法中,则必须转义反斜杠。
let jsonStr = """
"status": "success",
"data": "\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\""
"""
你得到了嵌套的 JSON。键 data
的值是另一个 JSON 字符串,必须单独反序列化
let jsonData = Data(jsonStr.utf8)
do
if let object = try JSONSerialization.jsonObject(with: jsonData) as? [String:String]
print(object)
if let dataString = object["data"] as? String
let dataStringData = Data(dataString.utf8)
let dataObject = try JSONSerialization.jsonObject(with: dataStringData) as? [String:String]
print(dataObject)
catch
print(error)
或者 – 付出更多的努力,但 – 对 (De)Codable
协议更满意
struct Response : Decodable
private enum CodingKeys : String, CodingKey case status, data
let status : String
let person : Person
init(from decoder: Decoder) throws
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(String.self, forKey: .status)
let dataString = try container.decode(String.self, forKey: .data)
person = try JSONDecoder().decode(Person.self, from: Data(dataString.utf8))
struct Person : Decodable
let name, address : String
let jsonStr = """
"status": "success",
"data": "\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\""
"""
let jsonData = Data(jsonStr.utf8)
do
let result = try JSONDecoder().decode(Response.self, from: jsonData)
print(result)
catch
print(error)
【讨论】:
如何更改 jsonStr 的值?因为我从 API 获得了 jsonStr(无法更改)。 对不起,我不明白。 数据必须是"\"name\":\"asd\",\"address\":\"Street 1st\"",不能更改。或者你知道如何将数据改为双反斜杠吗? 需要第二个反斜杠才能按字面意思使用它,例如在 Playground 中。服务器只发送 一个 反斜杠。 哦,我知道了,我先试试。谢谢@vadian【参考方案2】:你的代码有错误,因为你用“”“json”“”这样的代码编写它,
还有
data
是 String
不是字典,所以你需要转换为数据然后 JSONSerialization
再次
检查代码我将您的响应添加到 Json 文件中并解析它,并正常工作
所以只需将它写在名为 data.json 的 json 文件中
"status": "success",
"data": "\"name\":\"asd\",\"address\":\"Street 1st\""
并使用它:
guard let jsonFile = Bundle.main.path(forResource: "data", ofType: "json") else return
guard let data = try? Data(contentsOf: URL(fileURLWithPath: jsonFile), options: .mappedIfSafe) else return
if let response = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
print(response)
if let dataInDictionary = response as? [String:Any] , let addresData = dataInDictionary["data"] as? String
if let jsonData = addresData.data(using: .utf8),
let dictionary = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as? [String:Any]
print(dictionary)
【讨论】:
【参考方案3】:这是另一个基于答案@vadian的例子
Swift 4 - 使用 Codable
这是我收到的 json:
"error_code": 0,
"result":
"responseData": "\"emeter\":\"get_realtime\":\"voltage_mv\":237846,\"current_ma\":81,\"power_mw\":7428,\"total_wh\":1920,\"err_code\":0"
带有反斜杠的 JSON 部分等于:
"emeter":
"get_realtime":
"voltage_mv": 237846,
"current_ma": 81,
"power_mw": 7428,
"total_wh":19201,
"err_code":0
这是我使用的代码:
import Foundation
class RealtimeEnergy: Codable
let errorCode: Int
let result: ResultRealtimeEnergy?
let msg: String?
enum CodingKeys: String, CodingKey
case errorCode = "error_code"
case result, msg
init(errorCode: Int, result: ResultRealtimeEnergy?, msg: String?)
self.errorCode = errorCode
self.result = result
self.msg = msg
class ResultRealtimeEnergy: Codable
let responseData: String
var emeter: Emeter
enum CodingKeys: String, CodingKey
case responseData
required init(from decoder: Decoder) throws
let container = try decoder.container(keyedBy: CodingKeys.self)
responseData = try container.decode(String.self, forKey: .responseData)
let dataString = try container.decode(String.self, forKey: .responseData)
emeter = try JSONDecoder().decode(Emeter.self, from: Data(dataString.utf8))
class Emeter: Codable
let emeter: EmeterClass
init(emeter: EmeterClass)
self.emeter = emeter
class EmeterClass: Codable
let getRealtime: GetRealtime
enum CodingKeys: String, CodingKey
case getRealtime = "get_realtime"
init(getRealtime: GetRealtime)
self.getRealtime = getRealtime
class GetRealtime: Codable
let voltageMv, currentMa, powerMw, totalWh: Int
let errCode: Int
enum CodingKeys: String, CodingKey
case voltageMv = "voltage_mv"
case currentMa = "current_ma"
case powerMw = "power_mw"
case totalWh = "total_wh"
case errCode = "err_code"
init(voltageMv: Int, currentMa: Int, powerMw: Int, totalWh: Int, errCode: Int)
self.voltageMv = voltageMv
self.currentMa = currentMa
self.powerMw = powerMw
self.totalWh = totalWh
self.errCode = errCode
【讨论】:
以上是关于序列化包含转义(反斜杠和双引号)的 JSON 字符串 Swift 返回格式错误的对象的主要内容,如果未能解决你的问题,请参考以下文章