2016-03-28 25 views
3

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

:文字列は次のようになります3倍(つまり、[String: [[Double]]]が私が試した1つのモデルです)。どんなに私は何をすべきか、私はこれらの線に沿ってエラーが出るん:

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の感覚も持っていました。別の方法や別のモデリングが明示的なサブタイプで追加できますが、それは必要なものを与えることができますが、私はドキュメントから何をすべきかを困惑することはできません。

答えて

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値を持つオブジェクトのようなものは?): これは動作するようです。

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というの出力がいた:私は、次のunittestのでこれをテストした

{ 
    "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を使って辞書を設定することで 'ハック'を使用できます。これを行うために次のようなデータモデルが必要になります

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を実装する必要があります。それがどのように機能するかを確認するには、回避策の単体テストを参照してください。

+0

残念ながら、「結果」に返される正確なキーは可変なので、ネストされた結果構造を構築することはできません - 私はそれを不定集合の[string:[value ]]辞書要素。それらをすべてオプションとしてリストする私の唯一の希望ですか? – Feldur

+0

私はあなたが私がここでやったトリックでそれを解決できると思う:https://github.com/evermeer/EVWordPressAPI/blob/master/EVWordPressAPI/EVWordpressData.swift#L332 setValue forUndefinedKeyを使ってキャプチャできるようにするすべての 'プロパティ'はそれらが実際のプロパティではなく、ローカルの辞書にデータを設定します。私は後であなたのためにそれを働かせます... –

+0

有望です。次に、私は遊び場で働いているものすべてを持っていると私に言いたいと思います。 – Feldur