【发布时间】:2019-01-28 21:48:53
【问题描述】:
我一直在使用 app.quicktype.io 来生成解码 JSON 的代码。我现在面临一个我以前从未见过的问题。
首先,我有这个简单的结构:
import Foundation
struct GenericDM: Codable {
let status, statusMessage: String
let result: [Result]
enum CodingKeys: String, CodingKey {
case status
case statusMessage = "status_message"
case result
}
}
struct Result: Codable {
let applicationID, applicationName, applicationType, suFirstName: String
let suMiddleName, suLastName, suAge, suDob: String
let suRace: String
let suAddress: SuAddress
let createdTime, updatedTime: Int
enum CodingKeys: String, CodingKey {
case applicationID = "application_id"
case applicationName = "application_name"
case applicationType = "application_type"
case suFirstName = "su_first_name"
case suMiddleName = "su_middle_name"
case suLastName = "su_last_name"
case suAge = "su_age"
case suDob = "su_dob"
case suRace = "su_race"
case suAddress = "su_address"
case createdTime = "created_time"
case updatedTime = "updated_time"
}
}
struct SuAddress: Codable {
let addrLine1, addrLine2, stName, addrCity: String
let addrState, addrCounty, addrPin: String
enum CodingKeys: String, CodingKey {
case addrLine1 = "addr_line_1"
case addrLine2 = "addr_line_2"
case stName = "st_name"
case addrCity = "addr_city"
case addrState = "addr_state"
case addrCounty = "addr_county"
case addrPin = "addr_pin"
}
}
func newJSONDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
decoder.dateDecodingStrategy = .iso8601
}
return decoder
}
func newJSONEncoder() -> JSONEncoder {
let encoder = JSONEncoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
encoder.dateEncodingStrategy = .iso8601
}
return encoder
}
// MARK: - URLSession response handlers
extension URLSession {
fileprivate func codableTask<T: Codable>(with url: URL, completionHandler: @escaping (T?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
return self.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
completionHandler(nil, response, error)
return
}
completionHandler(try? newJSONDecoder().decode(T.self, from: data), response, nil)
}
}
func genericDMTask(with url: URL, completionHandler: @escaping (GenericDM?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
return self.codableTask(with: url, completionHandler: completionHandler)
}
}
然后,我读取一个 JSON 文件并尝试解码来自不同类的数据:
let bundle = Bundle.main
let path = bundle.path(forResource: "MockGenericData", ofType: "json")
let jsonData = try? String.init(contentsOf: URL.init(fileURLWithPath: path!))
let genericDM = try? newGenericDMJSONDecoder().decode(GenericDM.self, from: jsonData)
我暂时需要先读取该模型文件,然后才能从后端获取它。
但是,我得到 Cannot invoke 'decode' with an argument list of type '(GenericDM.Type, from: String?)',我不明白为什么。
有人知道吗?
【问题讨论】:
-
什么是
newGenericDMJSONDecoder? -
你需要传递一个数据对象而不是一个字符串
-
顺便说一句,将字符串对象命名为 jsonData 非常具有误导性
-
可能不相关,但您不必使用
CodingKeys来满足您的特定需求,只需将解码器的keyDecodingStrategy设置为convertFromSnakeCase。例如,它将status_message转换为statusMessage -
你只需要使用 Data contentsOf URL 而不是 String init