动态解码JSON单个对象或对象数组

动态解码JSON单个对象或对象数组,json,swift,codable,decodable,Json,Swift,Codable,Decodable,假设我有一个来自GET方法的JSON响应数组,如下所示: [{ "id":"1", "Name":"John Doe", },{ "id":"2", "Name":"Jane Doe", }] 从使用id param的POST方法中,我只有1个对象JSON响应: { "id":"1", "Name":"John Doe", } 如何编写一个方法来动态解码这两个JSON? 目前,我使用的是: func convertJSON<T:Decod

假设我有一个来自GET方法的JSON响应数组,如下所示:

[{
    "id":"1",
    "Name":"John Doe",
},{
    "id":"2",
    "Name":"Jane Doe",
}]
从使用id param的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
    }
}
func-convertJSON(结果:Any?,模型:T.Type)->T?{
如果让res=结果{
做{
let data=try JSONSerialization.data(使用jsonObject:res,选项:JSONSerialization.WritingOptions.prettypted)
返回try JSONDecoder().decode(模型,发件人:数据)
}抓住{
打印(错误)
归零
}
}否则{
归零
}
}
该方法可用于使用动态模型解码单个对象,但我无法理解如何动态处理单个对象/对象数组

我能得到的最多的方法就是使用该方法的一个副本,但将T替换为 [T] 在方法参数和返回类型中,如果响应是数组

我愿意接受任何建议,任何帮助都将不胜感激,提前谢谢


编辑:如果这个问题是重复的,我不确定标记的答案怎么可能是一个解决方案。

一个解决方案可能是始终返回
[Model]?

在函数内部,首先尝试解码为
模型
,成功后返回一个数组,其中包含单个解码对象。如果失败,则尝试解码为
[Model]
,成功后返回解码对象,否则返回nil

我使用示例JSON创建了一个结构:

struct Person: Codable {
  let id, name: String

  enum CodingKeys: String, CodingKey {
    case id
    case name = "Name"
  }
}
然后,我创建了一个结构,其中有两种方法可以从
字符串
或可选的
数据
进行解码

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))
 }
}
然后结构将更改为如下内容:

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))
 }
}

你能展示你的模型吗?所以你有两个方法,一个用于post,另一个用于get right?你可以使用参数有条件地调用你的方法,比如
convertJSON(result:json,model:model.self)
,用于单个对象。当你需要对象的数组时,只需调用convertJSON(结果:json,model:[model].self),它就会返回
[model]?
对象。@Jok3r我的模型与Aaron的答案相似,是的,有2个method@nayem这将触发“无法使用类型为”的参数列表调用“convertJSON”(结果:Any?,模型:[Model.Type])“errorThank,Aaron,使用条件与我想要实现的非常接近,但是返回总是数组,所以我使用Any?代替,然后使用if let value=returnValue as?[Model]{..}检查值的类型调用后,是否有任何方法将返回值定义为模型数组或单个模型?更新为以枚举形式返回一个值,可能包含:单个值、多个值或一个错误。希望有帮助。
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!!!!")
}