问题描述
我正在尝试解析此JSON响应
{
"payload": {
"bgl_category": [{
"number": "X","name": "","parent_number": null,"id": 48488,"description": "Baustellenunterk\u00fcnfte,Container","children_count": 6
},{
"number": "Y","id": 49586,"description": "Ger\u00e4te f\u00fcr Vermessung,Labor,B\u00fcro,Kommunikation,\u00dcberwachung,K\u00fcche","children_count": 7
}]
},"Meta": {
"total": 21
}
}
我想在TableViewCell中查看的只是number
和description
这是我到目前为止想要做的:
//MARK: - BGLCats
struct BGLCats: Decodable {
let Meta : Meta!
let payload : Payload!
}
//MARK: - Payload
struct Payload: Decodable {
let bglCategory : [BglCategory]!
}
//MARK: - BglCategory
struct BglCategory: Decodable {
let descriptionField : String
let id : Int
let name : String
let number : String
let parentNumber : Int
}
//MARK: - Meta
struct Meta: Decodable {
let total : Int
}
API请求:
fileprivate func getBgls() {
guard let authToken = getAuthToken() else {
return
}
let headers = [
"content-type" : "application/json","cache-control": "no-cache","Accept" : "application/json","Authorization": "\(authToken)"
]
let request = NSMutableuRLRequest(url: NSURL(string: "https://api-dev.com")! as URL,cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.allHTTPHeaderFields = headers
let endpoint = "https://api-dev.com"
guard let url = URL(string: endpoint) else { return }
URLSession.shared.dataTask(with: request as URLRequest) {(data,response,error) in
guard let data = data else { return }
do {
let BGLList = try JSONDecoder().decode(BglCategory.self,from: data)
print(BGLList)
dispatchQueue.main.sync { [ weak self] in
self?.number = BGLList.number
self?.desc = BGLList.descriptionField
// self?.id = BGLList.id
print("Number: \(self?.number ?? "UnkNown" )")
print("desc: \(self?.desc ?? "UnkNown" )")
// print("id: \(self?.id ?? 0 )")
}
} catch let jsonError {
print("Error Serializing JSON:",jsonError)
}
}.resume()
}
但是我遇到了错误:
Error Serializing JSON: keyNotFound(CodingKeys(stringValue: "childrenCount",intValue: nil),Swift.DecodingError.Context(codingPath: [],debugDescription: "No value associated with key CodingKeys(stringValue: \"childrenCount\",intValue: nil) (\"childrenCount\").",underlyingError: nil))
解决方法
这里有一些问题。
您(大多数情况下)正确地创建了模型,但是只有两个不匹配:
struct BglCategory: Decodable {
let description : String // renamed,to match "description" in JSON
let parentNum: Int? // optional,because some values are null
// ...
}
第二个问题是您的模型属性是 camelCased ,而JSON是 snake_cased 。 JSONDecoder具有.convertFromSnakeCase
实例来自动处理。您需要先在解码器上进行设置。
第三个问题是,您需要解码根对象BGLCats
,而不是BglCategory
。
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase // set the decoding strategy
let bglCats = try decoder.decode(BGLCats.self,from: data) // decode BGLCats
let blgCategories = bglCats.payload.bglCategory
,
问题是JSONDecoder不知道例如bglCategory
在JSON有效负载中表示为bgl_category
。如果JSON名称与变量名称不同,则需要对CodingKeys
实施Decodable
在您的情况下:
struct BglCategory: Decodable {
let descriptionField : String
let id : Int
let name : String
let number : String
let parentNumber : Int?
enum CodingKeys: String,CodingKey {
case id,name,number
case descriptionField = "description"
case parentNumber = "parent_number"
}
}
struct Payload: Decodable {
let bglCategory : [BglCategory]!
enum CodingKeys: String,CodingKey {
case bglCategory = "bgl_category"
}
}