我的项目包括动态数据,当控制器更改时这些数据会发生变化,因此,有时我的数据可能是:
[
{
"callDescription":"TEST 16/12",
"callDuration":"5-8 Minutes",
"callID":0,
"callMade":false,
"callMade_dateTime":"false_1608151560.0",
"dateTime":1608044666,
"type":"Breakfast Call"
},
{
"callDescription":"TEST 16/12",
"callDuration":"5-8 Minutes",
"callID":0,
"callMade":false,
"callMade_dateTime":"false_1608151560.0",
"dateTime":1608044666,
"type":"Breakfast Call"
},
]
然后运行一段代码,我的数据现在就运行了。
[
{
"callDescription":"TEST 16/12",
"callDuration":"5-8 Minutes",
"callID":0,
"callMade":false,
"callMade_dateTime":"false_1608151560.0",
"dateTime":1608044666,
"type":"Breakfast Call"
},
null
]
当再次请求数据时,它将导致valueNotFound错误。
跳过/处理任何为null的索引的最佳方法是什么?
下面是我的API代码:
class Service {
static let shared = Service()
let BASE_URL = "https://url.com"
func fetchClient(completion: @escaping ([Calls]) -> ()) {
guard let url = URL(string: BASE_URL) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
// handle error
if let error = error {
print("Failed to fetch data with error: ", error)
return
}
guard let data = data else {return}
do {
let myDecoder = JSONDecoder()
let calls = try myDecoder.decode([Calls].self, from: data)
completion(calls)
} catch let error {
print("Failed to create JSON with error: ", error)
}
}.resume()
}
Calls
模型:
struct Calls: Decodable {
let callDescription, callDuration, callMade_dateTime: String
let callID: Int
let dateTime: Date
let callMade: Bool
let type: String
}
发布于 2020-12-16 17:23:05
快速解决方案:
let calls = try myDecoder.decode([Calls].self, from: data)
completion(calls)
=>
let calls = try myDecoder.decode([Calls?].self, from: data)
completion(calls.compactMap{ $0 })
让我们简化这个示例(在编写真正的JSON之前,我开始编写答案):
struct Custom: Codable {
let data: String
}
let jsonString = """
[{"data": "Hello"}, {"data": "world"}]
"""
let jsonString2 = """
[{"data": "Hello"}, null, {"data": "world"}]
"""
因此,JSON中的某些值可能为null。那就是我们可以随意使用的地方。
func test(json: String) {
do {
print("Testing with [Custom].self: \(json)")
let customs = try JSONDecoder().decode([Custom].self, from: json.data(using: .utf8)!)
print("Result: \(customs)")
} catch {
print("Error: \(error)")
}
}
func test2(json: String) {
do {
print("Testing with [Custom?].self: \(json)")
let customs = try JSONDecoder().decode([Custom?].self, from: json.data(using: .utf8)!)
print("Result with optionals: \(customs)")
let unwrapped = customs.compactMap { $0 }
print("Result unwrapped: \(unwrapped)")
} catch {
print("Error: \(error)")
}
}
test(json: jsonString)
test(json: jsonString2)
test2(json: jsonString)
test2(json: jsonString2)
输出:
$>Testing with [Custom].self: [{"data": "Hello"}, {"data": "world"}]
$>Result: [Custom(data: "Hello"), .Custom(data: "world")]
$>Testing with [Custom].self: [{"data": "Hello"}, null, {"data": "world"}]
$>Error: valueNotFound(Swift.KeyedDecodingContainer<.Custom.CodingKeys>, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 1", intValue: 1)], debugDescription: "Cannot get keyed decoding container -- found null value instead.", underlyingError: nil))
$>Testing with [Custom?].self: [{"data": "Hello"}, {"data": "world"}]
$>Result with optionals: [Optional(.Custom(data: "Hello")), Optional(.Custom(data: "world"))]
$>Result unwrapped: [.Custom(data: "Hello"), .Custom(data: "world")]
$>Testing with [Custom?].self: [{"data": "Hello"}, null, {"data": "world"}]
$>Result with optionals: [Optional(.Custom(data: "Hello")), nil, Optional(.Custom(data: "world"))]
$>Result unwrapped: [.Custom(data: "Hello"), .Custom(data: "world")]
https://stackoverflow.com/questions/65327183
复制相似问题