我很确定我的模型基于数据是正确的,我无法弄清楚为什么会出现格式错误?
JSON:
{
"1596193200":{
"clientref":1,
"type":"breakfast"
},
"1596200400":{
"clientref":0,
"type":"lunch"
},
"1596218400":{
"clientref":2,
"type":"dinner"
}
}
型号:
struct Call: Decodable {
let clientref: Int?
let type: String?
}
用用于从URL解码json数据的代码编辑更新的问题:
class CallService {
static let shared = CallService()
let CALLS_URL = "url.com/Calls.json"
func fetchCalls(completion: @escaping ([Call]) -> ()) {
guard let url = URL(string: CALLS_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.localizedDescription)
return
}
guard let data = data else {return}
do {
let call = try JSONDecoder().decode([Call].self, from: data)
completion(call)
} catch let error {
print("Failed to create JSON with error: ", error.localizedDescription)
}
}.resume()
}
}
答案 0 :(得分:3)
我强烈建议学习如何调试:它包括查找位置,获取哪些信息,从何处获取等等,最后进行修复。
这是一件好事,您可以打印错误,而大多数初学者则不用。
print("Failed to create JSON with error: ", error.localizedDescription)
=>
print("Failed to create JSON with error: ", error)
您会得到一个更好的主意。
第二,如果失败,则打印字符串化的数据。您应该拥有JSON,没错。但是我经常看到关于该问题的问题,但实际上答案根本不是JSON(API从未声明它将返回JSON),而作者却遇到了错误(自定义404等),并且确实得到了XML / HTML消息错误等。
因此,当解析失败时,我建议这样做:
print("Failed with data: \(String(data: data, encoding: .utf8))")
检查输出是否为有效的JSON(很多在线验证器或执行此操作的应用程序)。
现在:
根据数据,我很确定我的模型是正确的
是的,是的,不是。
首次亮相时使用Codable的小技巧(不使用嵌套的东西):相反。
如果还没有,请让您的结构可编码(我使用过Playgrounds)
struct Call: Codable {
let clientref: Int?
let type: String?
}
do {
let calls: [Call] = [Call(clientref: 1, type: "breakfast"),
Call(clientref: 0, type: "lunch"),
Call(clientref: 2, type: "dinner")]
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted]
let jsonData = try encoder.encode(calls)
let jsonStringified = String(data: jsonData, encoding: .utf8)
if let string = jsonStringified {
print(string)
}
} catch {
print("Got error: \(error)")
}
输出:
[
{
"clientref" : 1,
"type" : "breakfast"
},
{
"clientref" : 0,
"type" : "lunch"
},
{
"clientref" : 2,
"type" : "dinner"
}
]
它看起来不像。我只能使用数组将多个调用放入单个变量内,这就是您要进行解码的意思,因为您编写了[Call].self
,所以您期望的是Call
数组。我们缺少“ 1596218400”部分。等等,这可能是顶级词典吗?是。您可以看到{}
及其使用“键”的事实,而不是一个接一个地列出...
等等,但是既然我们打印了完整的错误,那么现在更有意义了吗?
typeMismatch(Swift.Array<Any>,
Swift.DecodingError.Context(codingPath: [],
debugDescription: "Expected to decode Array<Any> but found a dictionary instead.",
underlyingError: nil))
修复:
let dictionary = try JSONDecoder().decode([String: Call].self, from: data)
completion(dictionary.values) //since I guess you only want the Call objects, not the keys with the numbers.
答案 1 :(得分:1)
根据您提供的代码,您似乎在尝试解码Array<Call>
,但是在JSON中,数据的格式为Dictionary<String: Call>
。
您应该尝试:
let call = try JsonDecoder().decode(Dictionary<String: Call>.self, from: data)