SWIFTUI - Json 总是解码 returns keyNotFound
SWIFTUI - Json decoding always returns keyNotFound
当我尝试在 SwiftUI 中解码我的 JSON 时,它总是给出错误:
keyNotFound(CodingKeys(stringValue: "is_paid", intValue: nil)
Double
等某些值似乎确实有效,但其他类型似乎会出现此类错误。我一直在寻找这个答案超过 2 天,我为此感到很崩溃。
型号
struct Invoices: Decodable, Hashable, Identifiable {
let id: Int
let is_paid: Int
let total: Double
let invoice_id: String
}
不知何故 id 和 total 给出了正确的值:
success([KlantenTest.InvoiceTest(id: 22, total: 30.0), KlantenTest.InvoiceTest(id: 26, total: 29.9959), KlantenTest.InvoiceTest(id: 28, total: 363.0), KlantenTest.InvoiceTest(id: 31, total: 240.1608), KlantenTest.InvoiceTest(id: 32, total: 29.9959)])
函数
func getCategorByAPI() -> Void {
let url = URL(string: "\(self.Api_URL)/api/v1/webhook/invoices/\(self.Api_token)/\(self.UserToken ?? self.Default)")!
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(self.Token ?? "")", forHTTPHeaderField: "Authorization")
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
URLSession.shared.jsonDecodableTask(with: request, decoder: decoder) { (result: Result<[InvoiceTest], Error>) in
print(result)
switch result {
case .success(let person):
print("InvoiceID: \(person)")
case .failure(let error):
print(error)
}
}.resume()
}
分机
enum URLError: Error {
case noData, decodingError
}
extension URLSession {
/// A type safe URL loader that either completes with success value or error with Error
func jsonDecodableTask<T: Decodable>(with url: URLRequest, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result<T, Error>) -> Void) -> URLSessionDataTask {
self.dataTask(with: url) { (data, response, error) in
DispatchQueue.main.async {
guard error == nil else {
completion(.failure(error!))
return
}
guard let data = data, let _ = response else {
completion(.failure(URLError.noData))
return
}
do {
let decoded = try decoder.decode(T.self, from: data)
completion(.success(decoded))
} catch {
completion(.failure(error))
}
}
}
}
func jsonDecodableTask<T: Decodable>(with url: URL, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result<T, Error>) -> Void) -> URLSessionDataTask {
self.jsonDecodableTask(with: URLRequest(url: url), decoder: decoder, completion: completion)
}
}
JSON
[
{
"id": 28,
"invoice_id": "20210126075159",
"total": 363,
"is_paid": 1,
},
{
"id": 31,
"invoice_id": "20210126075161",
"total": 240.1608,
"is_paid": 1,
},
{
"id": 32,
"invoice_id": "20210126075162",
"total": 29.9959,
"is_paid": 1,
}
]
如您所见,这些值实际上在那里,所以我不明白错误是从哪里来的,因为当我尝试下面的函数时,它确实适用于相同的模型 Invoices
let Url = URL(string: "\(self.Api_URL)/api/v1/webhook/invoices/\(self.Api_token)/\(self.UserToken ?? self.Default)")!
var request = URLRequest(url: Url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(self.Token ?? "")", forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: request) { (data, res, err) in
//check response status and err
guard let data = data else { return }
do {
let invoice = try JSONDecoder().decode([Invoices].self, from: data)
self.invoices = invoice
} catch {
print("Failed to decode: \(error)")
}
}.resume()
PS。我也试过通过[GetInvoices]
调用
struct GetInvoices: Decodable {
let invoices: [Invoices]
}
但是那连id或者Invoices
能找到的total都找不到,所以没用.
使用的代码来自:
您的问题在:.convertFromSnakeCase
is_paid
正在被解码为 isPaid
,与 invoice_id
相同。
当我尝试在 SwiftUI 中解码我的 JSON 时,它总是给出错误:
keyNotFound(CodingKeys(stringValue: "is_paid", intValue: nil)
Double
等某些值似乎确实有效,但其他类型似乎会出现此类错误。我一直在寻找这个答案超过 2 天,我为此感到很崩溃。
型号
struct Invoices: Decodable, Hashable, Identifiable {
let id: Int
let is_paid: Int
let total: Double
let invoice_id: String
}
不知何故 id 和 total 给出了正确的值:
success([KlantenTest.InvoiceTest(id: 22, total: 30.0), KlantenTest.InvoiceTest(id: 26, total: 29.9959), KlantenTest.InvoiceTest(id: 28, total: 363.0), KlantenTest.InvoiceTest(id: 31, total: 240.1608), KlantenTest.InvoiceTest(id: 32, total: 29.9959)])
函数
func getCategorByAPI() -> Void {
let url = URL(string: "\(self.Api_URL)/api/v1/webhook/invoices/\(self.Api_token)/\(self.UserToken ?? self.Default)")!
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(self.Token ?? "")", forHTTPHeaderField: "Authorization")
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
URLSession.shared.jsonDecodableTask(with: request, decoder: decoder) { (result: Result<[InvoiceTest], Error>) in
print(result)
switch result {
case .success(let person):
print("InvoiceID: \(person)")
case .failure(let error):
print(error)
}
}.resume()
}
分机
enum URLError: Error {
case noData, decodingError
}
extension URLSession {
/// A type safe URL loader that either completes with success value or error with Error
func jsonDecodableTask<T: Decodable>(with url: URLRequest, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result<T, Error>) -> Void) -> URLSessionDataTask {
self.dataTask(with: url) { (data, response, error) in
DispatchQueue.main.async {
guard error == nil else {
completion(.failure(error!))
return
}
guard let data = data, let _ = response else {
completion(.failure(URLError.noData))
return
}
do {
let decoded = try decoder.decode(T.self, from: data)
completion(.success(decoded))
} catch {
completion(.failure(error))
}
}
}
}
func jsonDecodableTask<T: Decodable>(with url: URL, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result<T, Error>) -> Void) -> URLSessionDataTask {
self.jsonDecodableTask(with: URLRequest(url: url), decoder: decoder, completion: completion)
}
}
JSON
[
{
"id": 28,
"invoice_id": "20210126075159",
"total": 363,
"is_paid": 1,
},
{
"id": 31,
"invoice_id": "20210126075161",
"total": 240.1608,
"is_paid": 1,
},
{
"id": 32,
"invoice_id": "20210126075162",
"total": 29.9959,
"is_paid": 1,
}
]
如您所见,这些值实际上在那里,所以我不明白错误是从哪里来的,因为当我尝试下面的函数时,它确实适用于相同的模型 Invoices
let Url = URL(string: "\(self.Api_URL)/api/v1/webhook/invoices/\(self.Api_token)/\(self.UserToken ?? self.Default)")!
var request = URLRequest(url: Url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(self.Token ?? "")", forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: request) { (data, res, err) in
//check response status and err
guard let data = data else { return }
do {
let invoice = try JSONDecoder().decode([Invoices].self, from: data)
self.invoices = invoice
} catch {
print("Failed to decode: \(error)")
}
}.resume()
PS。我也试过通过[GetInvoices]
struct GetInvoices: Decodable {
let invoices: [Invoices]
}
但是那连id或者Invoices
能找到的total都找不到,所以没用.
使用的代码来自:
您的问题在:.convertFromSnakeCase
is_paid
正在被解码为 isPaid
,与 invoice_id
相同。