【发布时间】:2020-04-04 17:08:57
【问题描述】:
我有一个包含嵌套字典的 json 对象,我正在尝试将其解析为 swift:
{
"ambientLightColor" : [100.0, 200.0, 300.0],
"lights" : {
"light1" : {"position" : [ 5, 5, 0], "direction" : [0,0,0], "color" : [0.0,0.7,0.3]},
"light2" : {"position" : [-5, 5, 0], "direction" : [0,0,0], "color" : [0.8,0.2,0.1]},
"light3" : {"position" : [ 0,-5, 0], "direction" : [0,0,0], "color" : [0.3,0.3,0.9]}
}
}
由于根对象是一个字典,其键为字符串,因此我将其转换为开头,如https://developer.apple.com/swift/blog/?id=37 示例中所做的那样
if let scene = sceneJSON as? [String: Any] {
if let ambientRGB = scene["ambientLightColor"] as? [f1] {
ambientLightColor = f3(ambientRGB[0],ambientRGB[1],ambientRGB[2])
}
if let lights = scene["lights"] as? [String: Any] {
for (lightName, properties) in lights {
let position = properties["position"]
let direction = properties["direction"]
let color = properties["color"]
self.lights.append(Light(position: f3(position[0], position[1], position[2]), direction: f3(direction[0], direction[1], direction[2]), color: f3(color[0], color[1], color[2])))
}
}
}
由于根字典值首先被转换为“任何”,因此在使用条目时必须将它们转换为更可用的类型。这对于我使用 if let ... as? 的第一个条目来说已经足够简单了。 [f1] 在使用它们创建 float3 之前将字典值 [100.0, 200.0, 300.0] 转换为单个浮点数组(我不确定如何从浮点数组直接转换为 float3 但这并不重要)。
第二种情况有点困难,因为它再次包含另一个嵌套字典,尽管我不想为每个单独的元素使用 if let,而是我想使用如上所示的 for 循环。现在我知道我还必须将属性字典值从 Any 类型转换为形式为 [String: [f1]] 的字典。
我已经尝试在第一个字典转换中转换它:
if let lights = scene["lights"] as? [String: [String: [f1]] {
for (lightName, properties) in lights {
let position = properties["position"]
let direction = properties["direction"]
let color = properties["color"]
self.lights.append(Light(position: f3(position[0], position[1], position[2]), direction: f3(direction[0], direction[1], direction[2]), color: f3(color[0], color[1], color[2])))
}
这给了我一个 [f1] 是可选的错误,并且当我运行它时也找不到任何匹配此类型的 json 对象。
我也试过
if let lights = scene["lights"] as? [String: [String: Any] {
for (lightName, properties) in lights {
let position = properties["position"] as! [f1]
let direction = properties["direction"] as! [f1]
let color = properties["color"] as! [f1]
self.lights.append(Light(position: f3(position[0], position[1], position[2]), direction: f3(direction[0], direction[1], direction[2]), color: f3(color[0], color[1], color[2])))
}
虽然这给了我任何关于无法将 NSNumber 桥接到 float 的错误,但当它们在数组中时很难修复。
我也试过
if let lights = scene["lights"] as? [String: Any] {
for case let (lightName, properties as? [String:[f1]]) in lights {
let position = properties["position"]
let direction = properties["direction"]
let color = properties["color"]
self.lights.append(Light(position: f3(position[0], position[1], position[2]), direction: f3(direction[0], direction[1], direction[2]), color: f3(color[0], color[1], color[2])))
}
这似乎是编写解决方案的好方法,但 swift 不会接受字典对括号内的类型转换。
非常感谢一个简洁的方式来做到这一点。 谢谢。
【问题讨论】:
-
f1和f3是什么?它们在哪里定义? -
考虑使用
Codable或至少像SwiftyJSON 这样的库。手动选项真的很痛苦。 -
@Alexander-ReinstateMonica 道歉,它们是 Float 和 SIMD3 的类型别名
-
@Yonat Codable 似乎是一个更好的解决方案,尽管我认为没有任何方法可以解释对象中存在的不同参数,因为结构具有明确定义的属性,而不是能够选择只有在场的人。我快速浏览了 SwiftyJSON,我认为它可能是最合适的。谢谢!
-
" 以任何方式解释对象中存在的不同参数,因为结构具有明确定义的属性,而不是只能从存在的属性中进行选择" 你能解释一下你的意思吗?
标签: ios swift dictionary types casting