2016-08-07 14 views
5

Próbuję analizować następujące JSON:Swift: flatMap do słownika

{ 
    "String For Key 1": [ 
    "Some String A", 
    "Some String B", 
    "Some String C", 
    ], 
    "String For Key 2": [ 
    "Some String D", 
    "Some String E", 
    "Some String F" 
    ], 
    "String For Key 3": [ 
    "Some String G", 
    "Some String H", 
    "Some String I", 
    ], 
    "String For Key 4": [ 
    "Some String J", 
    "Some String K", 
    "Some String L" 
    ], 
    "String For Key 5": [ 
    "Some String M", 
    "Some String N", 
    "Some String O" 
    ], 
    "String For Key 6": [ 
    "Some String P", 
    "Some String Q", 
    "Some String R" 
    ] 
} 

Jestem również po to tutorial. To na Github w Playground

Na przykład, są one parsowanie Array słowników korzystając typealias JSONDictionary = [String: AnyObject]

muszę analizować Dictionary który ma Key który String i Value że jest Array. Dlatego: typealias JSONDictionary = [String: [AnyObject]] i otrzymuję błąd podczas zwracania flatMap.

extension Resource { 
    init(url: NSURL, parseJSON: AnyObject -> A?) { 
     self.url = url 
     self.parse = { data in 
      let json = try? NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: [AnyObject]] 
      //This is where I get an error 
      return json.flatMap(parseJSON) 
     } 
    } 
} 

Błąd:

Cannot convert value of type `AnyObject -> A? to expected argument type `([String: [AnyObject]]?) -> _? 

Jak mogę uzyskać słownik z Keys jako String i Values jako Array? Chciałbym, aby ich podejście było zgodne z Generic.

Odpowiedz

5

Rodzaj jsonString jest Dictionary<String, Array<String>> Można nadać jej typ jak Dictionary<String, AnyObject>

AnyObject może zawierać klasę i struct tj Array, Dictionary, String, Int, Obj C Klasy Stąd Array<String> jest reprezentowany przez AnyObjectnie[AnyObject]

let jsonString:[String: AnyObject] = 
[ 
    "String For Key 1": [ 
    "http://www.urlToSomePathA.jpg", 
    "http://www.urlToSomePathB.jpg", 
    "http://www.urlToSomePathC.jpg", 
    ], 
    "String For Key 2": [ 
    "http://www.urlToSomePathD.jpg", 
    "http://www.urlToSomePathE.jpg", 
    "http://www.urlToSomePathF.jpg" 
    ] 
] 

// Now you can map a function on the value type 
let values = jsonString.flatMap { $0.1 as? [String] } 
print(values) 
// RESULT: [["http://www.urlToSomePathA.jpg", "http://www.urlToSomePathB.jpg", "http://www.urlToSomePathC.jpg"], ["http://www.urlToSomePathD.jpg", "http://www.urlToSomePathE.jpg", "http://www.urlToSomePathF.jpg"]] 

Aktualizacja

let keys = jsonString.flatMap { $0.0 } // ["String For Key 1", "String For Key 2"] 

Jak komentował @dffri, można użyć klawiszy nieruchomości na słowniku, który powróci LazyMapCollection które będą realizować tylko wtedy, gdy dostęp do obiektu wewnątrz.

let keys = jsonString.keys 
+0

Dzięki. To nie drukuje 'kluczy'? Jak uzyskać klucze jako 'klucz' i' wartość' jako 'Tablica'? – user1107173

+0

@ user1107173 Zaktualizowałem odpowiedź, możesz dostać się do klawiszy za pomocą 'let keys = jsonString.flatMap {$ 0.0}' – Khundragpan

+1

Uwaga: nie ma potrzeby używania 'flatMap' dla kluczy, ponieważ nie ma tam próby rzucenia (tylko' ' niech klucze = jsonString.map {$ 0.0} 'wystarczą). Alternatywnie użyj właściwości 'keys' ze słownika, aby uzyskać klucze jako leniwą kolekcję:' let keys = jsonString.keys'. – dfri