Swift 4解析json为变量
我想让苹果公司增加新的Codable功能,但我无法解决此问题. 我有一个像这样的json输出
Im trying to get my head around the new Codable feature Apple has added but Im not able to solve this problem. I have a json output which is like this
{
"Afpak": {
"id": 1,
"race": "hybrid",
"flavors": [
"Earthy",
"Chemical",
"Pine"
],
"effects": {
"positive": [
"Relaxed",
"Hungry",
"Happy",
"Sleepy"
],
"negative": [
"Dizzy"
],
"medical": [
"Depression",
"Insomnia",
"Pain",
"Stress",
"Lack of Appetite"
]
}
}
}
我有一个类似
struct Strain: Codable {
var name: String
var id: Int
var race: String
var flavors: [String]
var effects: [String: [String]]
}
因此很明显它将失败,因为我的json中没有名称键.名称应该是"Afpak",我环顾四周,但是大多数教程都没有给出任何有关如何解决此问题的示例,他们只是做了[String:Strain]
,这不是我所需要的.无论如何,有没有将字典的键设置为我的名称变量?
so obviously it will fail because there is no name key inside my json. The name should be "Afpak", I have looked around but most tutorials didnt give any example on how to solve this problem, they just did [String:Strain]
which is not what I need. Is there anyway set the key of my dictionary to my name variable?
您可以使用一个小技巧来解决未知的关键问题:为您的Strain
结构创建一个辅助结构,使该辅助结构Codable
,将响应解码为[String:Helper]
,然后创建一个自定义初始化程序,该初始化程序带有2个输入参数,菌株名称和Helper
实例.
You can use a small trick to get around the unknown key issue: create a helper struct for your Strain
struct, make that helper struct Codable
, decode the response as [String:Helper]
, then create a custom initializer that takes 2 input arguments, the name of the strain and a Helper
instance.
通过这种方式,您可以将name
存储为Strain
的属性,并且不需要复杂的解码即可避免未知的顶级Dictionary
密钥的问题.
This way you can store the name
as a property of Strain
and you won't need an overcomplicated decoding to circumvent the issue of the unknown top level Dictionary
key.
struct Strain {
var name: String
var id: Int
var race: String
var flavors: [String]
var effects: [String: [String]]
init(from helper: StrainHelper, with name:String){
self.name = name
self.id = helper.id
self.race = helper.race
self.flavors = helper.flavors
self.effects = helper.effects
}
}
struct StrainHelper: Codable {
var id: Int
var race: String
var flavors: [String]
var effects: [String: [String]]
}
do {
let strainHelper = try JSONDecoder().decode([String:StrainHelper].self, from: data)
guard let strainName = strainHelper.keys.first else {throw NSError(domain: "No key in dictionary",code: 404)}
let strain = Strain(from: strainHelper[strainName]!, with: strainName)
} catch {
print(error)
}