使用 Swift 3 解析 JSON
Posted
技术标签:
【中文标题】使用 Swift 3 解析 JSON【英文标题】:JSON Parsing using Swift 3 【发布时间】:2017-06-08 09:24:05 【问题描述】:我正在我的应用程序中调用一个肥皂服务。我从服务器收到此 JSON 响应
"CustomerName":"Muneer Ahmad/ Ejaz Ahmad (User) ",
"IsCorporate":false,
"ID":48,
"Name":"Muneer Ahmad/ Ejaz Ahmad (User) ",
"GroupID":null,
"GroupName":null,
"CustomerID":48
我已经尝试过在线教程的建议,但我无法解析数据。它给我的错误是“字符 0 周围的值无效”。我的代码是这样的
let is_URL: String = "http://labs2.unitedtracker.com/WTService.asmx?op=GetTerminalNumber"
let lobj_Request = NSMutableURLRequest(url: NSURL(string: is_URL)! as URL)
let session = URLSession.shared
lobj_Request.httpMethod = "POST"
lobj_Request.httpBody = is_SoapMessage.data(using: String.Encoding.utf8)
lobj_Request.addValue("labs2.unitedtracker.com", forHTTPHeaderField: "Host")
lobj_Request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
lobj_Request.addValue(String(is_SoapMessage.characters.count), forHTTPHeaderField: "Content-Length")
lobj_Request.addValue("http://tempuri.org/GetTerminalNumber", forHTTPHeaderField: "SOAPAction")
let task = session.dataTask(with: lobj_Request as URLRequest, completionHandler: data, response, error -> Void in
do
if let data = data,
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let customerID = json["CustomerID"] as? [[String: Any]]
print(customerID)
catch
print("Error deserializing JSON: \(error)")
if error != nil
print("Error: " + String(describing: error))
)
task.resume()
谁能告诉我我在做什么错。以及应该如何解析来自 Soap Service 的 JSON 响应。
这是来自我的服务器的完整响应。
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetAuthenticateUserResponse xmlns="http://tempuri.org/"><GetAuthenticateUserResult>["CustomerName":"Muneer Ahmad/ Ejaz Ahmad (User) ","IsCorporate":false,"ID":48,"Name":"Muneer Ahmad/ Ejaz Ahmad (User) ","GroupID":null,"GroupName":null,"CustomerID":48]</GetAuthenticateUserResult></GetAuthenticateUserResponse></soap:Body></soap:Envelope>
【问题讨论】:
catch
处理程序中的哪里收到错误?您可以将传入的data
记录为字符串吗?
不!我从 catch 处理程序中得到错误。当我尝试打印 customerID 时,它会说“字符 0 周围的值无效。”
为什么将 customerID 解析为字典数组?查看 JSON 响应,customerID 显然是一个 Int,因此您应该像这样解析它。 let customerID = json["CustomerID"] as? Int print(customerID)
提出了很好的观点@David Pasztor 实际上它是一个字符串值。我试试你说的。
显然服务器响应是 XML 而不是 JSON。
【参考方案1】:
lobj_Request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
你如何保证服务器会返回 json
作为响应?似乎它会返回text/xml
作为响应。
关于JSON解析,我建议SwiftyJSON。
更多建议
几年前,我使用了一个soap客户端引擎,它将wsdl
解析为objective-c
代码。今天,也许有些工具可以帮助您从wsdl
生成Swift
代码,以便与soap 服务器通信。
关于 wsdl 到 swift 客户端生成器
https://***.com/a/32798709/419348 作者发布了关于 wsdltoswift 的答案。 http://wsdl2swift.comwsdl2swift 网址。【讨论】:
开头的 JSON 是我从服务器接收的字符串。我们可以看到它是JSON格式的。 作为@zoul 的评论,您能否将传入的data
记录为字符串?
我已经更新了我的问题,现在服务器的完整响应也在其中
显然,<xml version ... >
是xml
格式,而不是json
。我已经更新了我的答案。也许调查一些 wsdl 解析工具可以帮助你。【参考方案2】:
问题是您从服务器接收 XML 并尝试将其解析为 JSON。您必须首先从 XML 信封中提取 JSON 有效负载。这是完整的回应:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetAuthenticateUserResponse xmlns="http://tempuri.org/">
<GetAuthenticateUserResult>["CustomerName":"Muneer Ahmad/ Ejaz Ahmad (User) ","IsCorporate":false,"ID":48,"Name":"Muneer Ahmad/ Ejaz Ahmad (User) ","GroupID":null,"GroupName":null,"CustomerID":48]</GetAuthenticateUserResult>
</GetAuthenticateUserResponse>
</soap:Body>
</soap:Envelope>
您需要将<GetAuthenticateUserResult>
标记的内容提取为字符串,只有这样您才能使用NSJSONSerialization
对其进行解析。有点像这样:
class Extractor: NSObject, XMLParserDelegate
var payload = ""
private var recording = false
let wantedElement = "GetAuthenticateUserResult"
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?,
qualifiedName qName: String?, attributes attributeDict: [String : String] = [:])
if elementName == wantedElement
recording = true
func parser(_ parser: XMLParser, foundCharacters string: String)
if recording
payload += string
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
recording = false
let response = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetAuthenticateUserResponse xmlns=\"http://tempuri.org/\"><GetAuthenticateUserResult>[\"CustomerName\":\"Muneer Ahmad/ Ejaz Ahmad (User)\",\"IsCorporate\":false,\"ID\":48,\"Name\":\"Muneer Ahmad/ Ejaz Ahmad (User) \",\"GroupID\":null,\"GroupName\":null,\"CustomerID\":48]</GetAuthenticateUserResult></GetAuthenticateUserResponse></soap:Body></soap:Envelope>"
let parser = XMLParser(data: response.data(using: .utf8)!)
let extractor = Extractor()
parser.delegate = extractor
parser.parse()
let payload = extractor.payload
let parsedPayload = try? JSONSerialization.jsonObject(with: payload.data(using: .utf8)!, options: [])
这给了你:
CustomerID = 48;
CustomerName = "Muneer Ahmad/ Ejaz Ahmad (User)";
GroupID = "<null>";
GroupName = "<null>";
ID = 48;
IsCorporate = 0;
Name = "Muneer Ahmad/ Ejaz Ahmad (User) ";
XML 提取代码有点笨,因为我不知道有什么更好的内置 XML 解析器。
【讨论】:
【参考方案3】:您的代码:
let customerID = json["CustomerID"] as? [[String: Any]]
print(customerID)
将customerID
视为字典而不是字符串。
应该是:
let customerID = json["CustomerID"] as? String
print(customerID)
您应该使用其他方式的网络请求和 JSON 解析器,例如 Alamofire and AlamofireObjectMapper。
【讨论】:
【参考方案4】:错误是将String
包装成[[String:Any]]
而不是这个:
if let data = data,
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let customerID = json["CustomerID"] as? [[String: Any]]
print(customerID)
试试这个:
if let data = data,
let json = try JSONSerialization.jsonObject(with: data) as? [[String: Any]],
let customerID = json["CustomerID"] as? String
print(customerID)
【讨论】:
customerId
在 JSON 响应中看起来像一个数字:"CustomerID":48
。所以也许let customerID = json["CustomerID"] as? Int
会更合适。
@Bala Karunakaran 我仍然遇到错误。 “JSON 文本没有以数组或对象开头,并且允许未设置片段的选项。”我想我应该尝试允许片段
@MattLeFleur 我试过了。 if let data = data, let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],让 customerID = json["CustomerID"] as?诠释打印(客户ID)。但仍然没有运气。给我同样的无效字符错误。
而不是 [String: Any] 尝试使用 [[String: Any]]以上是关于使用 Swift 3 解析 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Alamofire 在 Swift 3 中解析 JSON?
使用 Alamofire 在 swift 3 中解析 Json