我无法使用可解码和alamofire 3.0解析json响应数据。我收到以下错误。
错误keyNotFound(CodingKeys(stringValue:“ server_time”,intValue:nil),Swift.DecodingError.Context(codingPath:[],debugDescription:“与键CodingKeys(stringValue:\” server_time \“,intValue:没有关联的值: nil)(\“ server_time \”)。“,底层错误:nil))
这是我的代码。
解析代码
struct NewAucListJSON_Modal : Codable
{
let serverTime : String?
let error: Bool?
let display_name: String?
let list_id: Int?
let fk_com_id: Int?
let numFound : Int?
enum CodingKeys: String, CodingKey {
case data = "data"
case response = "response"
case numFound = "numFound"
case docs = "docs"
case display_name = "display_name", list_id = "list_id", fk_com_id = "fk_com_id"
case serverTime = "server_time"
case error = "error"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let response_data = try container.nestedContainer(keyedBy:
CodingKeys.self, forKey: .data)
self.serverTime = try response_data.decode(String.self, forKey: .serverTime)
self.error = try response_data.decode(Bool.self, forKey: .error)
let response = try response_data.nestedContainer(keyedBy: CodingKeys.self, forKey: .response)
let docs = try response.nestedContainer(keyedBy: CodingKeys.self, forKey: .docs)
display_name = try docs.decode(String.self, forKey: .display_name)
list_id = try docs.decode(Int.self, forKey: .list_id)
fk_com_id = try docs.decode(Int.self, forKey: .fk_com_id)
self.numFound = try response.decode(Int.self, forKey: .numFound)
}
func encode(to encoder: Encoder) throws {
}
}
JSON响应
{
"data": {
"responseHeader": {
"status": 0,
"QTime": 0,
"params": {
"q": "type:*",
"front_id:[1 TO 7] OR market:Nafed": "",
"fq": ["status:[100 TO 190]", "!template_id:(\"-40\" \"-50\")"],
"sort": "status DESC"
}
},
"response": {
"numFound": 7,
"start": 0,
"docs": [{
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}, {
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}, {
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}, {
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}, {
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}, {
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}, {
"fk_com_id": 6,
"list_id": 3089,
"display_name": "GDSMP-3089"
}]
}
},
"error": false,
"message": "Data Listed.",
"recordsFiltered": 0,
"recordsTotal": 0,
"server_time": "2019-01-08 15:03:28"
}
如果我对嵌套容器使用了不同的结构,则解析代码将变为:
struct AucListInfo : Codable
{
let docs : [AucListDoc]
let numFound : Int
enum CodingKeys: String, CodingKey {
case response = "response"
case docs = "docs"
case numFound = "numFound"
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var response = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .response)
try response.encode(self.docs, forKey: .docs)
try response.encode(self.numFound, forKey: .numFound)
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let response = try container.nestedContainer(keyedBy:
CodingKeys.self, forKey: .response)
self.docs = try response.decode([AucListDoc].self, forKey: .docs)
self.numFound = try response.decode(Int.self, forKey: .numFound)
}
}
struct AucListDoc : Codable
{
let display_name: String?
let list_id: Int?
let fk_com_id: Int?
private enum CodingKeys: String, CodingKey {
case display_name = "display_name", list_id = "list_id", fk_com_id = "fk_com_id"
}
init(display_name: String, list_id: Int, fk_com_id: Int) {
self.display_name = display_name
self.list_id = list_id
self.fk_com_id = fk_com_id
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
display_name = try container.decode(String.self, forKey: .display_name)
list_id = try container.decode(Int.self, forKey: .list_id)
fk_com_id = try container.decode(Int.self, forKey: .fk_com_id)
}
}
struct AucListJSON_Modal: Codable
{
// let data: AucListResponse?
let server_time : String
let error: Bool
let response : AucListInfo
enum CodingKeys: String, CodingKey {
case data = "data"
case response = "response"
case server_time = "server_time"
case error = "error"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let response = try container.nestedContainer(keyedBy:
CodingKeys.self, forKey: .data)
self.server_time = try response.decode(String.self, forKey: .server_time)
self.error = try response.decode(Bool.self, forKey: .error)
self.response = try response.decode(AucListInfo.self, forKey: .response)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var response = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
try response.encode(self.server_time, forKey: .server_time)
try response.encode(self.error, forKey: .error)
try response.encode(self.response, forKey: .response)
}
}
请帮助我解决错误
答案 0 :(得分:0)
不确定我是否正确理解您的意思,但我认为这就是您想要的。有点...:)
struct JSONResponse: Decodable {
struct AucListDoc: Decodable {
// I renamed some properties to suit conventions
let displayName: String
let listId: Int
let fkComId: Int
}
enum CodingKeys: String, CodingKey {
// don't need any key mapping here since the differences
// between the json's key names and the structs' properties'
// names are handled via the 'JSONDecoder's 'keyDecodingStrategy'
// (see the bottom of the answer)
case serverTime
case error
case data
case response
case numFound
case docs
}
// I only added the properties you seem to care about here
let serverTime: String
let error: Bool
let numFound: Int
let docs: [AucListDoc]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// you can immediately get 'serverTime' and 'error'
// from the outermost container
serverTime = try container.decode(String.self, forKey: .serverTime)
error = try container.decode(Bool.self, forKey: .error)
// since 'numFound' and 'docs' are contained in the nested
// 'response' container which itself is contained in the nested
// 'data' container you first have to get those nested containers
let data = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
let response = try data.nestedContainer(keyedBy: CodingKeys.self, forKey: .response)
// now you can get 'numFound' and 'docs' from the nested
// 'response' container
numFound = try response.decode(Int.self, forKey: .numFound)
docs = try response.decode([AucListDoc].self, forKey: .docs)
}
}
您可以像这样对jsonData
进行解码(不要忘记JSONDecoder
的{{1}}):
keyDecodingStrategy