问题描述
我正在调用API端点getChatMessages并按如下所示解码响应:
func getChatMessages(conversation: Int,pagesize: Int = 10,page: Int = 1,completion: @escaping(Result<ConversationDetails,APIError>) -> Void) {
{...some networking - configure request and start dataTask}
do {
let dateFormatter: DateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)
decoder.keyDecodingStrategy = .custom { codingKeys in
let lastKey = codingKeys.last!
if lastKey.intValue != nil || codingKeys.count != 2 { return lastKey }
if lastKey.stringValue == "count" || lastKey.stringValue == "conversation_participants" { return lastKey }
return AnyCodingKey(stringValue: "element")!
}
let result = try decoder.decode(ResponseMultipleElements<ConversationDetails>.self,from: data!)
completion(.success(result.detailresponse.element))
}catch {
print("Error is: ",error)
completion(.failure(.decodingError))
}
}
dataTask.resume()
}
这是ResponseMultipleElements结构
struct ResponseMultipleElements<T1: Decodable>: Decodable {
let statuscode: Int
let response_type: Int
let errormessage: String?
let detailresponse: Element<T1>
}
struct Element<T2: Decodable>: Decodable {
let count: Int
let element: T2
let conversation_participants: [ConversationParticipants]?
}
struct AnyCodingKey: CodingKey {
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
var intValue: Int? { return nil }
init?(intValue: Int) {
return nil
}
}
最后,是我的getChatMessages函数返回的ConversationDetails对象的结构
class ConversationDetails: Codable {
var messages: [ChatMessage]?
var conversation_participants: [ConversationParticipants]?
}
以下是来自getChatMessages API调用的响应:
问题:我收到typeMismatch(Swift.Dictionary<Swift.String,Any>,Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "detailresponse",intValue: nil),CodingKeys(stringValue: "element",intValue: nil)],debugDescription: "Expected to decode Dictionary<String,Any> but found an array instead.",underlyingError: nil))
现在遍历了所有内容,但找不到错误。
我不确定它是为哪个元素找到数组而不是期望的
解决方法
您的keyDecodingStrategy
告诉解码器将所有具有唯一一个父级(而不是count
或conversation_participants
)的字符串键都视为“元素”。 JSON中只有一个满足此条件的密钥-messages
下的detailresponse
。
messages
键将通过以下方式解码:
let element: T2
其中T2
是:
class ConversationDetails: Codable {
var messages: [ChatMessage]?
var conversation_participants: [ConversationParticipants]?
}
但是messages
实际上是JSON中的一个数组!
我建议您做的是解码ResponseMultipleElements<[ChatMessage]?>
。这样,T2
实际上就是预期的数组类型。
您应该向ConversationDetails
添加一个初始化程序,以允许您从一系列聊天消息和参与者中创建一个ConversationDetails
,
init(messages: [ChatMessage]?,conversation_participants: [ConversationParticipants]?) {
self.messages = messages
self.conversation_participants = conversation_participants
}
并在getChatMessages
中使用它:
let result = try decoder.decode(ResponseMultipleElements<[ChatMessage]?>.self,from: data!)
let convoDetails = ConversationDetails(
messages: result.detailresponse.element,conversation_participants: result.detailresponse.conversation_participants
)
completion(.success(convoDetails))