【问题标题】:How to represent nested array types for EVReflection如何表示 EVReflection 的嵌套数组类型
【发布时间】:2016-03-28 23:40:58
【问题描述】:

我正在尝试快速表示一个 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 中了解到,我可以添加另一种方法或具有显式子类型的不同建模来满足它的需求,但我无法从文档中弄清楚该怎么做。

【问题讨论】:

    标签: arrays swift json-deserialization


    【解决方案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。查看解决方法单元测试以了解其工作原理。

    【讨论】:

    • 不幸的是,将在“结果”中返回的精确键是可变的,所以我不能按照你的建议构建一个嵌套的结果结构——我需要它是一组不定的 [字符串:[[value]] 字典元素。我唯一希望将它们全部列为可选吗?
    • 我想你可以用我在这里做的技巧来解决这个问题:github.com/evermeer/EVWordPressAPI/blob/master/EVWordPressAPI/… 使用 setValue forUndefinedKey 这样你就可以捕获所有“属性”,而不会将它们作为真实属性,然后设置本地字典中的数据。稍后我会为您解决...
    • 很有希望。接下来,我希望您会告诉我您已经通过操场完成了所有工作,而我(无法使导入工作)会向您致敬!
    • 我更新了答案。也许有一天我真的会创建一个游乐场:-)
    • 我花了一些时间才弄好所有类型定义和转换器,但一旦我这样做了,更新后的答案就可以完美地与 Astro-Phys 网站配合使用。很高兴看到 EVReflection 中封装了多少能量!
    猜你喜欢
    • 1970-01-01
    • 2021-11-08
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多