Swiftui结构和解码JSON
使用urlsession从我的自定义API中获取水晶数据。尝试按标题列出。
我知道这里有些不正确,但不确定是什么。整个过程中,JSON词典解码,但没有运气。
是响应
struct多余的吗?还是可以简单地解码[string:Crystal]
用jsondecoder()
?任何方向和建议都得到赞赏。我知道如何使用阵列做到这一点,但是字典正在绊倒我。
获取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()
}
}
Using URLSession to get crystal data from my custom API. Trying to list by title.
I know something's incorrect here but not sure what. Looked all over SO for JSON dictionary decoding but no luck.
Is a Response
struct superfluous or can I simply decode [String:Crystal]
with JSONDecoder()
? Any and all direction and suggestion is appreciated. I knew how to do this with arrays but dictionaries are tripping me up.
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()
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个奇怪的API。您面临的问题在
Crystal
struct中。形而上学
似乎是String
的数组,但在至少一种情况下,它是一个简单的String
。编辑:
由于这是自定义API,您应该编辑它并返回
String
的数组,即使集合中只有一个元素。另外:
[String:Crystal]
。color
- >颜色
然后您可以使用:
原始:
如果此数据是静态的(不更改),则可以逃脱以下解决方案:
并将其解码:
但是有一种方法可以使此更强大的方法和能够将其视为
[String:gemwitharray]
。您需要在gemwitharray
struct中使用自定义初始化器。在其中尝试将形而上学
解码为[String]
,如果失败,则创建数组,解码并将其作为string
附加。并像:
This is a somewhat strange API. The problem you are facing is within the
Crystal
struct.metaphysical
seems to be an array ofString
but in at least one case it is a simpleString
.Edit:
As this is a custom API you should edit it and return an array of
String
even if there is only one element in the collection.In addition:
[String:Crystal]
.color
->colour
Then you can use:
Original:
If this data is static (does not change) you could get away with the following solution:
And decoding it like:
But there is a way to make this more robust and capable of treating it as
[String:GemWithArray]
. You would need to use a custom initializer in theGemWithArray
struct. In it try to decodemetaphysical
to an[String]
and if it fails create an array, decode and append it asString
.and decoding it like: