动态解码JSON单个对象或对象数组
假设我有一个来自GET方法的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
[{
"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!!!!")
}