Array aus Dictionaries in JSON

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Array aus Dictionaries in JSON

    Hallo, ich bin neue hier und bin auch noch recht neu in Sachen Swift 4.
    Bin jetzt seit ein paar Tagen dabei und nun leider auf ein Problem gestoßen bei dem ich seit heute morgen nicht weiterkomme und vielleicht doch etwas Hilfe brauche.


    Hier mein Code:

    Quellcode

    1. func getAllBlocks () { //Abruf der JSON Daten zum Überblick.
    2. let JSONurl = "https://chain.api.btc.com/v3/block/latest,5000,2" //URL festlegen
    3. let url = URL(string: JSONurl ) //String umwandeln in eine URl
    4. let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in //Datenabruf
    5. if error != nil {
    6. print("ERROR \(String(describing: error))")
    7. return
    8. }
    9. do {
    10. let loadedJSON = try JSONSerialization.jsonObject(with: data!) as! [String:Any] //JSON verarbeiten
    11. print(loadedJSON)
    12. for (key, value) in loadedJSON {
    13. print(key)
    14. if (key == "data") { //prüfen auf key "data" und dann dessen Dict abgreifen
    15. print("data")
    16. //Hier ist das Problem. Am Ende sollen alle Daten aus dem JSON Abruf in ein Array damit ich sie von dort aus weiter verwenden kann.
    17. }}
    18. } catch{ print("Error beim JSON decodieren! \(error)") }
    19. }
    20. task.resume()
    21. }
    Alles anzeigen


    Mein Problem ist, das ich beim Abruf des JSON von: chain.api.btc.com/v3/block/5000,5001 eine Struktur zurückerhalte, die ich irgendwie nicht verarbeitet bekomme. Wenn ich statt zwei Bitcoin-Blöcke (die zahlen am Ende) nur einen abrufe,, kann ich es verarbeiten. Sobald es aber mehr als einer ist, entsteht im JSON noch ein Array das ich nicht aufgelöst bekomme.


    Hat hier jemand eine Idee wie ich an die jeweiligen Daten aus den Dictionaries der einzelnen Blöcke komme?
    Vielen Dank für jede Hilfe!
  • Mal auf die Schnelle zusammengeklöppelt und nicht sehr elegant, aber vielleicht hilft's Dir ja gedanklich weiter:

    Quellcode

    1. var startData: [Any] = [1, [10, 11, 12]]
    2. for e in startData {
    3. if let array = e as? [Int] {
    4. print(array) // [10, 11, 12]
    5. } else if let singleValue = e as? Int {
    6. print(singleValue) // 1
    7. }
    8. }

    Statt [Int] und Int müßtest Du dann halt nach [[String: Any] und [String: Any] unterscheiden… ;)
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Ich habe zum Thema insgesamt noch mal ein bißchen rumgespielt.

    Den Ansatz in meinem letzten Post könnte man auch als generische Funktion umsetzen, die immer, wenn möglich, ein Array eines gegebenen Typs zurückgibt, auch wenn eben nur die Instanz eines Typs mitgegeben wird.

    Quellcode

    1. func flatCast<T>(_ x: Any, asArrayOfElementsOf: T.Type) -> [T]? {
    2. switch x {
    3. case let x as [T]: return x
    4. case let x as T: return [x]
    5. case let x as [T?]: return x.flatMap{$0} // Yes, that's tricky! ;)
    6. default: return nil
    7. }
    8. }
    9. var startData: [Any] = [1, [9, nil, 7], [10, 11, 12],]
    10. for e in startData {
    11. if let e = flatCast(e, asArrayOfElementsOf: Int.self) {
    12. print(e)
    13. }
    14. }
    15. // [1]
    16. // [9, 7]
    17. // [10, 11, 12]
    Alles anzeigen
    Ich bin mir sicher, User wie @MacDan werden bei der Betrachtung solchen Codes ihre Hände über dem Kopf zusammenschlagen und Swift wieder mal als kryptisches Teufelszeugs verdammen.^^ :D

    Und ich weiß, ich bin grottenschlecht darin, vernünftige Namen und Bezeichner zu finden. Wie gut, daß ich keine öffentlichen Libs und Frameworks designe! ;)

    Ausgehend von dem Code des Thread-Eröffners habe ich dann dazu auch noch was gebastelt:

    Brainfuck-Quellcode

    1. let urlString = "https://chain.api.btc.com/v3/block/5003,666,1000000000000000"
    2. let url = URL(string: urlString)!
    3. func cast<T>(_ x: Any, asArrayWithElementsOfType: T.Type) -> [T]? {
    4. switch x {
    5. case let x as [T]: return x
    6. case let x as T: return [x]
    7. case let x as [T?]: return x.flatMap{$0} // Yes, that's tricky! ;)
    8. default: return nil
    9. }
    10. }
    11. func withBTCJSON(at url: URL, _ callback: @escaping ([[String: Any]]?, Error?) -> Void) {
    12. let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    13. if let error = error { callback(nil, error); return }
    14. do {
    15. guard
    16. let data = data,
    17. let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
    18. let dataElement = json["data"],
    19. let dataElements = cast(dataElement, asArrayWithElementsOfType: [String: Any].self)
    20. else {
    21. // 'error' is nil here; use a proper custom error instance instead!
    22. callback(nil, error); return
    23. }
    24. callback(dataElements, nil)
    25. }
    26. catch let error { callback(nil, error) }
    27. }
    28. task.resume()
    29. }
    30. func btcJSONCallback(blocks: [[String: Any]]?, error: Error?) {
    31. if let error = error { print("Error:", error) }
    32. for block in blocks ?? [[:]] {
    33. print("BEGIN BLOCK >>>>>>>>>>")
    34. for (key, value) in block {
    35. print(key, value)
    36. }
    37. print("END BLOCK <<<<<<<<<<\n")
    38. }
    39. }
    40. withBTCJSON(at: url, btcJSONCallback(blocks:error:))
    Alles anzeigen

    Das ganze auch anbei als Playground zum weiteren Rumspielen…^^

    Anmerkungen zum Code:
    1.) Bis auf die eingehende URL werden keine weiteren explicitly unwrapped optionals, aka ! benutzt. Ich wiederhole mich: Das ist kein Schnuller, den man dem Compiler ins Maul stopft, um ihn ruhig zu stellen! if let und guard let sind gute Freunde, die man nutzen sollte!

    2.) Alle Fehlermeldungen werden abgefangen und an eine zentralle Callback-Stelle weitergereicht. Fehlerbehandlung ist etwas, was in Beispielcodes leider immer wieder audgelassen wird… :(

    Ich habe Zweifel, ob der Thread-Eröffner seinen eigenen Thread noch weiter verfolgt, aber ich schreibe das hier trotzdem, in der Hoffnung, daß vielleicht andere stille Mitleser davon profitieren können…
    Dateien
    • _btc.zip

      (11,03 kB, 401 mal heruntergeladen, zuletzt: )
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • torquato schrieb:


    Ich bin mir sicher, User wie @MacDan werden bei der Betrachtung solchen Codes ihre Hände über dem Kopf zusammenschlagen und Swift wieder mal als kryptisches Teufelszeugs verdammen.^^ :D

    Es heißt MCDan und nicht MacDan, so viel Zeit muss sein. :D

    Aber Du hast recht, eine leserliche Syntax ist dies nicht und daran wird sich bei Swift wohl leider auch nichts mehr ändern.
  • MCDan schrieb:


    Es heißt MCDan und nicht MacDan, so viel Zeit muss sein. :D

    Jaaaa… Alter! Hab vorgeschrieben und dann beim C&P vergessen an dieser Stelle das System abzufragen… ;( Fühl Dich trotzdem geehrt, daß ich an Dich gedachbt habe; hast ja gewußt, daß Du gemeint warst…^^

    PS: Eigentlich bin ich jetzt neugierig, warum MC und nicht Mac…?
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • nussratte schrieb:

    sollte nicht … ein weiterer Vorteil sein nun weniger Code schreiben zu müssen?
    Swift sieht irgendwie immer nach unnötig viel Code aus

    Wirklich? Mmmhhh… Kann ich jetzt nicht so nachvollziehen. Ich habe eher die Befürchtung, daß Swift manchmal unleserlich wird, weil es zu 'kompakt' benutzt wird; will sagen: Zuviel Voodoo in kurzen Zeilen. Mein flatCast<T>(:T.Type) -> [T]? z. B. von oben geht so in die Richtung. ;)

    Egal. Zeig uns doch mal wie obige Aufgabe kürzer und leserlicher in Objective-C geht!
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Mir ist nicht klar, welche Vorteile es hat, wenn ein Source Code jetzt nur 5 und nicht 10 oder 15 Zeilen lang ist. ?(

    Wichtig für mich ist vor allem die Lesbarkeit und Verständlichkeit von Source Code. Weiterhin sollte der Code einfach zu debuggen sein, d.h. ich verwende lieber Zwischenschritte, als alles in eine Zeile mit x Befehlen zu packen.

    Aber da hat wohl jeder andere Vorstellungen und Vorlieben. ;)
  • MCDan schrieb:

    Mir ist nicht klar, welche Vorteile es hat, wenn ein Source Code jetzt nur 5 und nicht 10 oder 15 Zeilen lang ist. ?(

    Wichtig für mich ist vor allem die Lesbarkeit und Verständlichkeit von Source Code. Weiterhin sollte der Code einfach zu debuggen sein, d.h. ich verwende lieber Zwischenschritte, als alles in eine Zeile mit x Befehlen zu packen.

    Aber da hat wohl jeder andere Vorstellungen und Vorlieben. ;)
    Dann passt das Argument mit unnötig viel Code aber auch nicht. Hat jeder so seine Vorlieben und es wird ja auch in den nächsten Jahren (gehe ich mal von aus) niemand gezwungen Swift zu nutzen.

    Ich schreibe auch nur "Basic" - Swift Code und wenn ich dann diesen komplizierten Mist sehe komme ich mir doch arg blöd vor.
  • @matz wenn du mich schon wieder gibst dann bitte korrekt.

    Ich habe nicht geschrieben das es unnötig ist sondern so aussieht.


    Für das was da eig nur gemacht wird, ist es echt viel Code und das passt nicht zu der von Apple und den Swift-Fanboys getätigten Aussage, man muss in Swift viel weniger schreiben.
    Also andersrum könnte ja ein Swift-Fanboy der dieser Meinung ist zeigen das Objective-C Code der das gleiche macht mehr ist.
    Ich weiß nicht immer wovon ich rede aber ich weiß das ich Recht habe. :saint:
  • nussratte schrieb:


    Für das was da eig nur gemacht wird, ist es echt viel Code und das passt nicht zu der von Apple und den Swift-Fanboys getätigten Aussage, man muss in Swift viel weniger schreiben.
    Also andersrum könnte ja ein Swift-Fanboy der dieser Meinung ist zeigen das Objective-C Code der das gleiche macht mehr ist.

    Jemand, der eine Behauptung aufstellt, steht in der Pflicht, diese auch zu belegen, nicht derjenige, der die Behaupung anzweifelt.

    "Die Erde ist ein Würfel!" Beweise Du das Gegenteil. Ich muß es ja nicht. Merkst Du was? ;)
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von torquato ()