如何表示 EVReflection 的嵌套数组类型

How to represent nested array types for EVReflection

我试图在 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"
}

我尝试了几种方法来对内部 "results" 字典进行建模,它以字符串作为键,并且始终具有两个元素数组的值,每个元素具有三个双精度值(即 [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 中了解到,我可以添加另一种方法或具有显式子类型的不同建模来满足它的需求,但我无法从文档中弄清楚该怎么做。

在 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 值的对象?)

更新: 这似乎有效。我使用以下单元测试对此进行了测试:

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"
}

更新二: 如下所述,行星 'keys' 不是一个固定的集合。所以实际上这应该作为字典来处理。要执行此类操作,您可以使用 'hack' 通过使用 setValue forKey 来填充字典。为此,您需要这样的数据模型:

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,那么你的行星层次结构将多出一个层次。如果您不想这样做,则可以通过将结果 属性 更改为字符串来解决此问题: [[NSNumber]] 然后您还需要实施 EVCustomDictionaryConverter。请参阅解决方法单元测试以了解其工作原理。