假设我有一个来自GET方法的JSON响应数组:
[{
"id":"1",
"Name":"John Doe",
},{
"id":"2",
"Name":"Jane Doe",
}]
从使用id参数的POST方法中,我只有1个对象JSON响应:
{
"id":"1",
"Name":"John Doe",
}
如何编写一种方法来动态解码两个JSON? 目前,这就是我正在使用的:
func convertJSON<T:Decodable>(result: Any?, model: T.Type) -> T? {
if let res = result {
do {
let data = try JSONSerialization.data(withJSONObject: res, options: JSONSerialization.WritingOptions.prettyPrinted)
return try JSONDecoder().decode(model, from: data)
} catch {
print(error)
return nil
}
} else {
return nil
}
}
该方法可用于使用动态模型对单个对象进行解码,但是我无法弄清楚它可以动态地处理单个对象/对象数组。
我能得到的最多就是使用方法的重复,但是用T代替T 如果响应为数组,则在方法参数和返回类型中使用[T]。
我愿意接受任何建议,感谢您的帮助。
编辑:如果该问题与this重复,则不确定标记的答案将如何解决。
答案 0 :(得分:0)
一种解决方案是始终返回[Model]?
。
在您的函数内部,首先尝试将其解码为Model
,如果成功,则返回一个数组,其中包含单个解码的对象。如果失败,则尝试解码为[Model]
,成功解码后返回解码的对象,否则返回nil。
使用示例JSON创建一个结构:
struct Person: Codable {
let id, name: String
enum CodingKeys: String, CodingKey {
case id
case name = "Name"
}
}
然后,我用两个方法创建了一个结构,以从String
或可选的Data
进行解码。
struct Json2Type<T: Decodable> {
// From data to type T
static public func convertJson(_ data: Data?) -> [T]? {
// Check data is not nil
guard let data = data else { return nil }
let decoder = JSONDecoder()
// First try to decode as a single object
if let singleObject = try? decoder.decode(T.self, from: data) {
// On success return the single object inside an array
return [singleObject]
}
// Try to decode as multiple objects
guard let multipleObjects = try? decoder.decode([T].self, from: data) else { return nil }
return multipleObjects
}
// Another function to decode from String
static public func convertJson(_ string: String) -> [T]? {
return convertJson(string.data(using: .utf8))
}
}
最后调用您喜欢的方法:
Json2Type<Person>.convertJson(JsonAsDataOrString)
更新:@ odin_123,可以使用Model
完成将[Model]
或enum
作为返回值的方法。我们甚至可以在其中添加错误条件,以避免返回可选值。让我们将枚举定义为:
enum SingleMulipleResult<T> {
case single(T)
case multiple([T])
case error
}
然后结构更改为如下内容:
struct Json2Type<T: Decodable> {
static public func convertJson(_ data: Data?) -> SingleMulipleResult<T> {
guard let data = data else { return .error }
let decoder = JSONDecoder()
if let singleObject = try? decoder.decode(T.self, from: data) {
return .single(singleObject)
}
guard let multipleObjects = try? decoder.decode([T].self, from: data) else { return .error }
return .multiple(multipleObjects)
}
static public func convertJson(_ string: String) -> SingleMulipleResult<T> {
return convertJson(string.data(using: .utf8))
}
}
您可以像以前一样调用它:
let response = Json2Type<Person>.convertJson(JsonAsDataOrString)
并使用开关检查每个可能的响应值:
switch(response) {
case .single(let object):
print("One value: \(object)")
case .multiple(let objects):
print("Multiple values: \(objects)")
case .error:
print("Error!!!!")
}