使用URLSession从我的自定义API中获取水晶数据。试着按标题列出。
我知道这里有些地方不对,但不确定是什么。查找了所有的JSON字典解码,但没有运气。
Response结构是多余的还是我可以简单地用JSONDecoder()解码[String:Crystal]?如有任何指导和建议,我们将不胜感激。我知道如何使用数组来完成这个任务,但是字典让我很不爽。
GET https://lit-castle-74820.herokuapp.com/api/crystals
{
"amethyst": {
"composition": "silicon dioxide",
"formation": "forms when gas bubbles occur in lava and become trapped",
"colour": "purple",
"metaphysical": [
"calming",
"healing",
"especially for headaches",
"fatigue, & anxiety"
]
},
"clear quartz": {
"composition": "silicon dioxide",
"formation": "forms when gas bubbles occur in lava and become trapped",
"colour": "colourless or appears white",
"metaphysical": "master healer for all ailments; amplifies the healing vibration of other stones placed nearby"
},
"moss agate": {
"composition": "silicon dioxide, commonly featuring manganese or iron",
"formation": "formed from weathered volcanic rock",
"colour": "colourless with specks of white, green, blue, or brown",
"metaphysical": [
"gentle healing",
"promotes tranquility",
"cures physical ailments (inflammation, cold & flu)"
]
},
"carnelian": {
"composition": "silicon dioxide with iron impurity",
"formation": "formed from a combination of the silica minerals quartz and moganite",
"colour": "orange or red often featuring yellow",
"metaphysical": [
"promotes life-force",
"vitality",
"energizes body and mind"
]
},
"spirit quartz": {
"composition": "silicon dioxide",
"formation": "forms when gas bubbles occur in lava and become trapped",
"colour": "purple, yellowish brown, light grey",
"metaphysical": [
"assists in spiritual journey",
"uplifts and promotes vibration"
]
},
"amazonite": {
"composition": "potassium feldspar",
"formation": "formed in deep sea igneous rocks that cool very slowly",
"colour": "blue or green with white speckles or lines",
"metaphysical": [
"Soothes anxiety and overthinking",
"helps heal emotional trauma"
]
},
"tourmaline": {
"composition": "silicate of boron and aluminum",
"formation": "Pegmatite pockets underground that slowly cool and form crystals",
"colour": "black or pink",
"metaphysical": [
"repels negative energy",
"highly protective"
]
},
"pyrite": {
"composition": "iron sulfide",
"formation": "forms in sedimentary rocks in low oxygen environments",
"colour": "gold",
"metaphysical": [
"abundance",
"good luck",
"emotional strength"
]
}
}struct Response: Codable {
let crystals: [String:Crystal]
}
struct Crystal: Codable, Identifiable {
var id = UUID()
let composition, formation, color: String
let metaphysical: [String]
}
struct ContentView: View {
@State private var crystals: [String:Crystal] = [:]
var body: some View {
List(crystals) { crystal in
(crystal.key)
}.onAppear(perform: loadData)
}
func loadData() {
guard let url = URL(string: "https://lit-castle-74820.herokuapp.com/api/crystals") else { return }
URLSession.shared.dataTask(with: url) { data, _, error in
guard let data = data else { return }
do {
let decodedResponse = try JSONDecoder().decode(Response.self, from: data)
DispatchQueue.main.async {
self.crystals = decodedResponse.crystals
}
} catch let jsonError as NSError {
print("JSON decode failed: \(jsonError)")
}
}.resume()
}
}发布于 2022-06-21 20:10:33
这是一个有点奇怪的API。您所面临的问题是在Crystal结构中。metaphysical似乎是一个String数组,但至少在一个例子中,它是一个简单的String。
编辑:
因为这是一个自定义API,所以您应该编辑它并返回一个String数组,即使集合中只有一个元素。
此外:
[String:Crystal].color -> colour中有一个错误
然后你可以使用:
try JSONDecoder().decode([String:Crystal].self, from: data)原件:
如果此数据是静态的(不改变),则可以使用以下解决方案:
struct Response: Codable {
let amethyst, mossAgate, carnelian, spiritQuartz, amazonite, tourmaline, pyrite: GemWithArray
let clearQuartz: GemWithoutArray
enum CodingKeys: String, CodingKey {
case amethyst
case clearQuartz = "clear quartz"
case mossAgate = "moss agate"
case carnelian
case spiritQuartz = "spirit quartz"
case amazonite, tourmaline, pyrite
}
}
struct GemWithArray: Codable {
let composition, formation, colour: String
let metaphysical: [String]
}
struct GemWithoutArray: Codable {
let composition, formation, colour, metaphysical: String
}把它解码成:
try JSONDecoder().decode(Response.self, from: data)但是有一种方法可以使它更加健壮,并且能够将它作为[String:GemWithArray]来处理。您需要在GemWithArray结构中使用自定义初始化程序。在它中,尝试将metaphysical解码到一个[String],如果它失败了,创建一个数组,将其解码并附加为String。
struct GemWithArray: Codable {
let composition, formation, colour: String
let metaphysical: [String]
enum CodingKeys: String, CodingKey{
case composition, formation, colour, metaphysical
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
composition = try container.decode(String.self, forKey: .composition)
formation = try container.decode(String.self, forKey: .formation)
colour = try container.decode(String.self, forKey: .colour)
if let metaphysical = try? container.decode([String].self, forKey: .metaphysical){
self.metaphysical = metaphysical
} else{
metaphysical = [try container.decode(String.self, forKey: .metaphysical)]
}
}
}把它解码成:
try JSONDecoder().decode([String:GemWithArray].self, from: data)https://stackoverflow.com/questions/72705733
复制相似问题