fra*_*yan 5 json nsjsonserialization swift jsondecoder
TL; DR
有没有一种方法可以使用JSONDecoder并编写一个函数,它只是从给定的json读出指定的可解码类型的字段值?
成像我有以下json:
{
"product":{
"name":"PR1",
"price":20
},
"employee":{
"lastName":"Smith",
"department":"IT",
"manager":"Anderson"
}
}
Run Code Online (Sandbox Code Playgroud)
我有2个Decodable结构:
struct Product: Decodable {
var name: String
var price: Int
}
struct Employee: Decodable {
var lastName: String
var department: String
var manager: String
}
Run Code Online (Sandbox Code Playgroud)
我想写一个函数
func getValue<T:Decodable>(from json: Data, field: String) -> T { ... }
Run Code Online (Sandbox Code Playgroud)
所以我可以这样称呼它:
let product: Product = getValue(from: myJson, field: "product")
let employee: Employee = getValue(from: myJson, field: "employee")
Run Code Online (Sandbox Code Playgroud)
这是可能的,JSONDecoder或者我应该弄乱JSONSerialization,首先读出给定json的"子树",然后将其传递给解码器?在swift中似乎不允许在泛型函数中定义结构.
Decodable假设您在设计时知道您想要的所有内容以启用静态类型.你想要的动态越多,你就越有创意.在这种情况下,定义通用编码键结构非常方便:
/// A structure that holds no fixed key but can generate dynamic keys at run time
struct GenericCodingKeys: CodingKey {
var stringValue: String
var intValue: Int?
init?(stringValue: String) { self.stringValue = stringValue }
init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" }
static func makeKey(_ stringValue: String) -> GenericCodingKeys { return self.init(stringValue: stringValue)! }
static func makeKey(_ intValue: Int) -> GenericCodingKeys { return self.init(intValue: intValue)! }
}
/// A structure that retains just the decoder object so we can decode dynamically later
fileprivate struct JSONHelper: Decodable {
let decoder: Decoder
init(from decoder: Decoder) throws {
self.decoder = decoder
}
}
func getValue<T: Decodable>(from json: Data, field: String) throws -> T {
let helper = try JSONDecoder().decode(JSONHelper.self, from: json)
let container = try helper.decoder.container(keyedBy: GenericCodingKeys.self)
return try container.decode(T.self, forKey: .makeKey(field))
}
let product: Product = try getValue(from: json, field: "product")
let employee: Employee = try getValue(from: json, field: "employee")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
478 次 |
| 最近记录: |