ios - 如何从 node.js 网络服务中获取数据并在 iOS 应用程序中显示?
问题描述
我有一个内置在 node.js 中的 REST API 网络服务,我可以通过 url 访问它。我需要将该数据导入 iOS 应用程序。目前,我在 HomeModel.swift 中使用的代码以字节的形式为我提供数据,而不是预期的:
{
"recordsets":[[{"USERCODE":"A", "PASSWORD":"SaYX^]Kc", "FIRSTNAME":"ADMINISTRATOR", "LASTNAME":" ", "USERCLASS":"1", "CONTACTNO":"2213"}]],
"recordset":[{"USERCODE":"A", "PASSWORD":"SaYX^]Kc", "FIRSTNAME":"ADMINISTRATOR", "LASTNAME":" ", "USERCLASS":"1", "CONTACTNO":"2213"}],
"output":{},
"rowsAffected":[1]
}
此外,当我尝试解析数据时,出现错误:
无法将“__NSSingleObjectArrayI”(0x7fff87a90f58)类型的值转换为“NSString”(0x7fff87b502e8)。2020-08-18 20:15:02.512836+0300 [11444:1203386] 无法将“__NSSingleObjectArrayI”(0x7fff87a90f58)类型的值转换为“NSString”(0x7fff87b502e8)。
我的 HomeModel.swift 文件中的代码如下:
import UIKit
protocol HomeModelDelegate {
func usersDownloaded(users:[User])
}
class HomeModel: NSObject {
var delegate: HomeModelDelegate?
let serviceUrl = "http://url.com/api/users"
func getUsers() {
//Download JSON data
let url = URL(string: serviceUrl)
if let url = url {
//Create a url session
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error == nil {
//Data successfully loaded and call the parseJson function on the data
self.parseJson(data: data!)
print(data!)
}
else {
//Some error occurred
print("Some error occurred")
}
}
task.resume()
}
//Notify the viewcontroller and pass the data back
}
func parseJson(data: Data) {
var usrArray = [User]()
//Parse the data into User struct
do {
//Parse the data into JSON Object
let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as! [String:String]
//Loop through each result in the JSON array
for jsonResult in jsonArray {
//Caste JSON result as a dictionary
let jsonDict = jsonResult as! [String : String]
//Create new User and set its properties
let usr = User(usrID: jsonDict["USERNAME"]!, firstName: jsonDict["FIRSTNAME"]!, lastName: jsonDict["LASTNAME"]!, password: jsonDict["PASSWORD"]!, usrClass: jsonDict["USERCLASS"]!)
//Add the user to the array
usrArray.append(usr)
}
//Pass the data array back to the delegate
delegate?.usersDownloaded(users: usrArray)
}
catch{
//Some error occurred
print("Some error occurred")
}
}
}
如何解决此问题并将“记录集”数据显示到我的控制台上?
解决方案
你得到的错误是因为方法中的这一行parseJson(data:)
:
let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as! [String:String]
这是为什么?
您正在尝试将您的 JSON 对象强制转换为键和值类型字符串的字典。键可能是字符串类型,但值肯定不是,这正是错误试图告诉你的。您正在尝试将 Array 转换为 String 永远不会发生的东西。
如果您查看上面粘贴的 JSON 中的第一个键值对,您可以看到键recordsets
是 String 类型,但对于值,这不是真的。值是 Array 类型,将其转换为键和值类型 String 的字典将失败。
您如何解决此问题并在控制台中显示记录集值?
我会在可解码协议的帮助下解决这个问题。
首先,我将声明我的DataTransferObject
并使其符合可解码协议。在那里,您可以看到属性与 JSON 中的键具有完全相同的名称。如果您拼错任何这些属性,解码 JSON 将失败,所以要小心。
struct DataTransferObject: Decodable {
let recordsets: [[User]]
let recordset: [User]
let output: OutputObject
let rowsAffected: [Int]
}
然后你必须声明你的DataTransferObject
all 中缺少的类型也符合 decodable 。因为User
对象中的属性与 JSON 中的键命名不同,所以您必须使用CodingKeys
枚举器将它们与 JSON 键相关联。
struct User: Decodable {
let usrID: String
let firstName: String
let lastName: String
let password: String
let usrClass: String
enum CodingKeys: String, CodingKey {
case usrID = "USERCODE"
case password = "PASSWORD"
case firstName = "FIRSTNAME"
case lastName = "LASTNAME"
case usrClass = "USERCLASS"
}
}
struct OutputObject: Decodable {
}
然后你可以修改你的parseJson(data:)
方法来使用JSONDecoder
对象来解码你的 JSON 和打印recordset
属性到控制台。
func parseJson(data: Data) {
do {
// Instantiate JSONDecoder object
let decoder = JSONDecoder()
// Decode JSON to DataTransferObject
let dto = try decoder.decode(DataTransferObject.self, from: data)
// Print out recordset property
print("*** Decoded recordset property: \(dto.recordset)")
} catch {
//Some error occurred
print("Some error occurred: \(error.localizedDescription)")
}
}
推荐阅读
- r - R:Kruskal-Wallis 测试循环遍历数据框中的指定列
- css - CSS 网格,网格单元的自动填充和自动调整大小
- c# - 使用 PasswordChar True 在文本框上显示文本
- sql - SQL 错误:ROW_NUMBER() OVER (PARTITION
- vue.js - NativeScript-Vue 找不到模块
- ios - UITableViewCell contentView 具有 autoResizingMask 约束“UIView-Encapsulated-Layout-Height”与自动调整大小的自动布局冲突
- c++ - 虚拟“默认”析构函数和显式空析构函数有什么区别?
- c - 线性搜索没有返回正确的索引
- python-3.x - sklearn 决策树分类器:如何控制每个拆分的最大分支数
- javascript - 为什么在事件处理函数外部定义的函数需要保存在事件处理函数内部的新变量中?