我正在尝试在swift中表示一个JSON结构,以便与EVReflection一起使用。字符串如下所示:
{
"date": 2457389.3333330001,
"results":
{
"sun": [[559285.95145709824, 202871.33591198301, 61656.198554897906], [127.6163120820332, 948.44727756795123, 406.68471093096883]],
... etc ...
"geomoon": [[-401458.60657087743, -43744.769596474769, -11058.709613333322], [8433.3114508170656, -78837.790870237863, -26279.67592282737]]
},
"unit": "km"
}
我尝试了几种方法对内部“结果”字典进行建模,该字典用字符串键入,并且始终具有两个元素的数组值,每个元素都有三个双精度数(即[String: [[Double]]]
是我尝试过的一种模式。无论我做什么,我都会犯这样的错误:
ERROR: valueForAny unkown type , type _NativeDictionaryStorage<String, Array<Array<Double>>>. Could not happen unless there will be a new type in Swift.
有没有人知道如何对此进行建模,以便EVReflection很开心?我也从短语Could not happen unless there will be a new type in Swift
中感觉到有另一种方法或不同的建模与我可以添加的显式子类型,它可以提供它所需要的东西,但我无法解释从文档中做什么。
答案 0 :(得分:1)
在Swift中,Double是一个结构。使用结构进行反射有一些限制。我更喜欢使用NSNumber。
我的第一个想法是这样的对象模型:
class MyObject: EVObject {
var date: NSNumber?
var results: Result?
var unit: String?
}
class Result: EVObject {
var sun: [[NSNumber]]?
var geomoon: [[NSNumber]]?
}
但是你的对象有一个嵌套值。到目前为止,我从来没有用这样的结构测试EVReflection。我稍后会尝试为此添加一个单元测试。如果内部数组是一个对象(类似于具有x,y和z值的对象?),那会更容易。
<强>更新强> 这似乎有效。我用以下unitTest测试了这个:
func testNestedArry() {
let json = "{\"date\": 2457389.3333330001,\"results\": { \"sun\": [[559285.95145709824, 202871.33591198301, 61656.198554897906], [127.6163120820332, 948.44727756795123, 406.68471093096883]], \"geomoon\": [[-401458.60657087743, -43744.769596474769, -11058.709613333322], [8433.3114508170656, -78837.790870237863, -26279.67592282737]] }, \"unit\": \"km\" }"
let myObject = MyObject(json: json)
print(myObject.toJsonString())
}
myObject的输出是:
{
"date" : 2457389.333333,
"results" : {
"sun" : [
[
559285.9514570982,
202871.335911983,
61656.19855489791
],
[
127.6163120820332,
948.4472775679512,
406.6847109309688
]
],
"geomoon" : [
[
-401458.6065708774,
-43744.76959647477,
-11058.70961333332
],
[
8433.311450817066,
-78837.79087023786,
-26279.67592282737
]
]
},
"unit" : "km"
}
更新2: 如下所述,行星'键'不是固定的集合。所以实际上这应该作为字典来处理。要做这样的事情,你可以使用setValue forKey填充字典来使用'hack'。为此,您需要一个这样的数据模型:
class MyObject: EVObject {
var date: NSNumber?
var results: Result?
var unit: String?
}
class Result: EVObject {
var planets = [String: [[NSNumber]]]()
// This way we can solve that the JSON has arbitrary keys
internal override func setValue(value: AnyObject!, forUndefinedKey key: String) {
if let a = value as? [[NSNumber]] {
planets[key] = a
return
}
NSLog("---> setValue for key '\(key)' should be handled.")
}
}
你必须要知道,如果你想为此创建json,你将在行星的层次结构中有一个额外的等级。如果您不想这样,那么可以通过将results属性更改为String来实现一种解决方法:[[NSNumber]]然后您还需要实现EVCustomDictionaryConverter。请参阅变通方法单元测试以了解其工作原理。