Swift错误JSONDecoder keyNotFound当尝试创建对象



需要从JSON中创建对象从API对象

JSON响应来自API

[
{
"CUSTOMER_ID": 1,
"CUSTOMER_CODE": "123",
"PERSONS": [
{
"FIRST_NAME": "Patrick",
"MID_NAME": "A.",
"LAST_NAME": "L."
},
{
"FIRST_NAME": "Nadine",
"MID_NAME": "N.",
"LAST_NAME": "Ricordo"
}
]
},
{
"CUSTOMER_ID": 2,
"CUSTOMER_CODE": "456",
"PERSONS": [
{
"FIRST_NAME": "Giulio",
"MID_NAME": "G.",
"LAST_NAME": "A."
}
]
},
{
"CUSTOMER_ID": 3,
"CUSTOMER_CODE": "789",
"PERSONS": [
{
"FIRST_NAME": "Vanessa",
"MID_NAME": null,
"LAST_NAME": "B"
},
{
"FIRST_NAME": "Nadine",
"MID_NAME": "D.",
"LAST_NAME": "Ricordo"
}
]
}
]

我还创建了如下结构体

struct Customer : Codable {
var CUSTOMER_ID: Int
var CUSTOMER_CODE: String
var PERSONS: Person
}
struct Person : Codable {
var FIRST_NAME: String
var MID_NAME: String? // can be null
var LAST_NAME: String
}

我ViewModel

class CustomerListViewModel: ObservableObject {

@Published var customers: [CustomerViewModel] = []

func getAllCustomers() {

let defaults = UserDefaults.standard
guard let token = defaults.string(forKey: "jsonwebtoken") else {
return
}

Webservice().getAllCustomers(token: token) { (result) in
switch result {
case .success(let customers):
DispatchQueue.main.async {
self.customers = customers.map(CustomerViewModel.init)
}
case .failure(let error):
print(error.localizedDescription) // output: AppName.NetworkError error 2.
}
}

}

}

struct CustomerViewModel {

let customer: Customer

let id = UUID()

var CUSTOMER_ID: Int {
return customer.CUSTOMER_ID
}

var CUSTOMER_CODE: String {
return customer.CUSTOMER_CODE
}

var PERSONS: Person {
return customer.PERSONS
}

解码在Webservice类

class Webservice {

func getAllCustomers(token: String, completion: @escaping (Result<[Customer], NetworkError>) -> Void) {

guard let url = URL(string: "https://myapi") else {
completion(.failure(.invalidURL))
return
}

var request = URLRequest(url: url)
request.addValue(token, forHTTPHeaderField: "access-token")

URLSession.shared.dataTask(with: request) { (data, response, error) in

guard let data = data, error == nil else {
completion(.failure(.noData))
return
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

do {
let customers = try decoder.decode(Array<Customer>.self, from: data)
print(customers)
completion(.success(customers))
} catch let error {
print("[Webservice] Decoding Error")
print(error)
completion(.failure(.decodingError))
return
}
}.resume()
}
[...]
}

误差

[Webservice] Decoding Error keyNotFound(CodingKeys(stringValue: "CUSTOMER_ID", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "CUSTOMER_ID", intValue: nil) ("CUSTOMER_ID"), with divergent representation cUstomerId, converted to c_ustomer_id.", underlyingError: nil))

后来我想打印(myCustomerViewModel.PERSONS[I].FIRST_NAME)使用我的ViewModel如果JSON中的值为空,我还需要null处理例如MID_NAME of "Vanessa">

更新1

后删除decoder.keyDecodingStrategy = .convertFromSnakeCase

我得到以下错误:

keyNotFound(CodingKeys(stringValue: "CUSTOMER_ID", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "CUSTOMER_ID", intValue: nil) ("CUSTOMER_ID").", underlyingError: nil))

删除这一行

decoder.keyDecodingStrategy = .convertFromSnakeCase

,因为你实际上没有从蛇形大小写转换键(最好添加CodingKeys以避免那些难看的大写名称)。

为了避免另一个错误,将PERSONS声明为数组

var PERSONS: [Person]

最新更新