Richtiges Parsen von JSON in Swift 3


123

Ich versuche, eine JSON-Antwort abzurufen und die Ergebnisse in einer Variablen zu speichern. Ich hatte Versionen dieses Codes in früheren Versionen von Swift funktionieren lassen, bis die GM-Version von Xcode 8 veröffentlicht wurde. Ich habe mir einige ähnliche Beiträge zu StackOverflow angesehen: Swift 2 Parsing JSON - Ein Wert vom Typ 'AnyObject' und JSON Parsing in Swift 3 kann nicht abonniert werden .

Es scheint jedoch, dass die dort vermittelten Ideen in diesem Szenario nicht zutreffen.

Wie analysiere ich die JSON-Antwort in Swift 3 korrekt? Hat sich etwas an der Art und Weise geändert, wie JSON in Swift 3 gelesen wird?

Unten ist der fragliche Code (er kann auf einem Spielplatz ausgeführt werden):

import Cocoa

let url = "https://api.forecast.io/forecast/apiKey/37.5673776,122.048951"

if let url = NSURL(string: url) {
    if let data = try? Data(contentsOf: url as URL) {
        do {
            let parsedData = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments)

        //Store response in NSDictionary for easy access
        let dict = parsedData as? NSDictionary

        let currentConditions = "\(dict!["currently"]!)"

        //This produces an error, Type 'Any' has no subscript members
        let currentTemperatureF = ("\(dict!["currently"]!["temperature"]!!)" as NSString).doubleValue

            //Display all current conditions from API
            print(currentConditions)

            //Output the current temperature in Fahrenheit
            print(currentTemperatureF)

        }
        //else throw an error detailing what went wrong
        catch let error as NSError {
            print("Details of JSON parsing error:\n \(error)")
        }
    }
}

Bearbeiten: Hier ist ein Beispiel der Ergebnisse des API-Aufrufs nachprint(currentConditions)

["icon": partly-cloudy-night, "precipProbability": 0, "pressure": 1015.39, "humidity": 0.75, "precipIntensity": 0, "windSpeed": 6.04, "summary": Partly Cloudy, "ozone": 321.13, "temperature": 49.45, "dewPoint": 41.75, "apparentTemperature": 47, "windBearing": 332, "cloudCover": 0.28, "time": 1480846460]

Können Sie die Beispieldaten ablegen, die von Ihrem API-Aufruf zurückgegeben wurden?
Benutzer

1
Ja, ich habe gerade ein Beispiel der Ergebnisse hinzugefügt, die nach dem Druck gedruckt wurden (currentConditions). Ich hoffe es hilft.
user2563039

Analysieren Sie json in swift4 mit dem codierbaren Protokoll stackoverflow.com/a/52931265/9316566
Naser Mohamed

Antworten:


172

Zu allererst nie Daten geladen werden synchron von einer Remote - URL , verwenden Sie immer asynchrone Methoden wie URLSession.

'Any' hat keine tiefgestellten Mitglieder

tritt auf, weil der Compiler keine Ahnung hat, um welchen Typ es sich bei den Zwischenobjekten handelt (z. B. currentlyin ["currently"]!["temperature"]), und weil Sie Foundation-Auflistungstypen verwenden, wie NSDictionaryder Compiler überhaupt keine Ahnung vom Typ hat.

Zusätzlich ist es in Swift 3 erforderlich, den Compiler über den Typ aller tiefgestellten Objekte zu informieren .

Sie müssen das Ergebnis der JSON-Serialisierung in den tatsächlichen Typ umwandeln.

Dieser Code verwendet URLSessionund ausschließlich Swift native Typen

let urlString = "https://api.forecast.io/forecast/apiKey/37.5673776,122.048951"

let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
  if error != nil {
    print(error)
  } else {
    do {

      let parsedData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
      let currentConditions = parsedData["currently"] as! [String:Any]

      print(currentConditions)

      let currentTemperatureF = currentConditions["temperature"] as! Double
      print(currentTemperatureF)
    } catch let error as NSError {
      print(error)
    }
  }

}.resume()

Um alle Schlüssel / Wert-Paare von currentConditionsIhnen zu drucken , könnten Sie schreiben

 let currentConditions = parsedData["currently"] as! [String:Any]

  for (key, value) in currentConditions {
    print("\(key) - \(value) ")
  }

Ein Hinweis zu jsonObject(with data:

Viele (es scheint , alle) Anleitungen vorschlagen .mutableContainersoder .mutableLeavesOptionen , die in Swift vollständig ist Unsinn. Die beiden Optionen sind ältere Objective-C-Optionen zum Zuweisen des Ergebnisses zu NSMutable...Objekten. In Swift ist jede variable standardmäßig veränderbar, und das Übergeben einer dieser Optionen und das Zuweisen des Ergebnisses zu einer letKonstanten hat überhaupt keine Auswirkung. Außerdem mutieren die meisten Implementierungen den deserialisierten JSON sowieso nie.

Die einzige (selten) Option , die in Swift nützlich ist , ist .allowFragmentsdie , wenn erforderlich, wenn das JSON Wurzelobjekt ein Werttyp sein könnte ( String, Number, Booloder null) , anstatt eine der Sammeltypen ( arrayoder dictionary). Aber normalerweise lassen Sie den optionsParameter weg , was bedeutet, dass keine Optionen verfügbar sind .

================================================== =========================

Einige allgemeine Überlegungen zum Parsen von JSON

JSON ist ein übersichtliches Textformat. Es ist sehr einfach, eine JSON-Zeichenfolge zu lesen. Lesen Sie die Zeichenfolge sorgfältig durch . Es gibt nur sechs verschiedene Typen - zwei Sammlungstypen und vier Werttypen.


Die Sammlungstypen sind

  • Array - JSON: Objekte in eckigen Klammern []- Swift: [Any]aber in den meisten Fällen[[String:Any]]
  • Wörterbuch - JSON: Objekte in geschweiften Klammern {}- Swift:[String:Any]

Die Werttypen sind

  • String - JSON: Beliebiger Wert in doppelten Anführungszeichen "Foo", auch "123"oder "false"- Swift:String
  • Zahl - JSON: numerische Werte nicht in doppelten Anführungszeichen 123oder 123.0- Swift: IntoderDouble
  • Bool - JSON: trueoder false nicht in doppelten Anführungszeichen - Swift: trueoderfalse
  • null - JSON: null- Swift:NSNull

Gemäß der JSON-Spezifikation müssen alle Schlüssel in Wörterbüchern sein String.


Grundsätzlich wird immer empfohlen, optionale Bindungen zu verwenden, um Optionen sicher auszupacken

Wenn das Stammobjekt ein dictionary ( {}) ist, wandeln Sie den Typ in um[String:Any]

if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [String:Any] { ...

und Werte durch Schlüssel mit abrufen ( OneOfSupportedJSONTypesist entweder JSON-Sammlung oder Werttyp wie oben beschrieben.)

if let foo = parsedData["foo"] as? OneOfSupportedJSONTypes {
    print(foo)
} 

Wenn das Stammobjekt ein Array ( []) ist, wandeln Sie den Typ in um[[String:Any]]

if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [[String:Any]] { ...

und iteriere durch das Array mit

for item in parsedData {
    print(item)
}

Wenn Sie ein Element an einem bestimmten Index benötigen, überprüfen Sie auch, ob der Index vorhanden ist

if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [[String:Any]], parsedData.count > 2,
   let item = parsedData[2] as? OneOfSupportedJSONTypes {
      print(item)
    }
}

In dem seltenen Fall, dass JSON einfach einer der Werttypen und nicht ein Auflistungstyp ist, müssen Sie die .allowFragmentsOption übergeben und das Ergebnis beispielsweise in den entsprechenden Werttyp umwandeln

if let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String { ...

Apple hat einen umfassenden Artikel im Swift-Blog veröffentlicht: Arbeiten mit JSON in Swift


================================================== =========================

In Swift 4+ Codablebietet das Protokoll eine bequemere Möglichkeit, JSON direkt in Strukturen / Klassen zu analysieren.

Zum Beispiel das angegebene JSON-Beispiel in der Frage (leicht modifiziert)

let jsonString = """
{"icon": "partly-cloudy-night", "precipProbability": 0, "pressure": 1015.39, "humidity": 0.75, "precip_intensity": 0, "wind_speed": 6.04, "summary": "Partly Cloudy", "ozone": 321.13, "temperature": 49.45, "dew_point": 41.75, "apparent_temperature": 47, "wind_bearing": 332, "cloud_cover": 0.28, "time": 1480846460}
"""

kann in die Struktur dekodiert werden Weather. Die Swift-Typen sind die gleichen wie oben beschrieben. Es gibt einige zusätzliche Optionen:

  • Zeichenfolgen, die ein darstellen, URLkönnen direkt als dekodiert werden URL.
  • Die timeGanzzahl kann wie Datebei der dekodiert werden dateDecodingStrategy .secondsSince1970.
  • snaked_cased JSON-Schlüssel können mit dem in camelCase konvertiert werdenkeyDecodingStrategy .convertFromSnakeCase

struct Weather: Decodable {
    let icon, summary: String
    let pressure: Double, humidity, windSpeed : Double
    let ozone, temperature, dewPoint, cloudCover: Double
    let precipProbability, precipIntensity, apparentTemperature, windBearing : Int
    let time: Date
}

let data = Data(jsonString.utf8)
do {
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .secondsSince1970
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let result = try decoder.decode(Weather.self, from: data)
    print(result)
} catch {
    print(error)
}

Andere codierbare Quellen:


Das ist sehr hilfreich. Ich bin nur neugierig, warum der obige Code keine sichtbare Ausgabe zeigt, wenn er auf einem Spielplatz ausgeführt wird.
user2563039

Wie oben erwähnt, müssen Sie das mehrdeutige Ergebnis dict!["currently"]!in ein Wörterbuch umwandeln, damit der Compiler sicher auf das nachfolgende Schlüsselabonnement schließen kann.
Vadian

1
Der Apple-Artikel ist ziemlich cool, aber ich konnte ihn aus irgendeinem Grund nicht mit Swift 3 zum Laufen bringen. Es beschwert sich über Typ [String: Any]? hat keine tiefgestellten Mitglieder. Es gab auch einige andere Probleme, aber ich konnte es umgehen. Hat jemand ein Beispiel für seinen Code, der tatsächlich ausgeführt wird?
Shades

@Shades Stellen Sie eine Frage und veröffentlichen Sie Ihren Code. Höchstwahrscheinlich hängt Ihr Problem mit unverpackten Optionen zusammen.
Vadian

Können Sie die Beispieldaten ablegen, die von Ihrem API-Aufruf zurückgegeben wurden?
Benutzer

12

Eine große Änderung, die mit Xcode 8 Beta 6 für Swift 3 passiert ist, war, dass die ID jetzt als importiert wird Anyund nicht mehr AnyObject.

Dies bedeutet, dass parsedDataes als Wörterbuch zurückgegeben wird, das höchstwahrscheinlich dem Typ entspricht [Any:Any]. Ohne einen Debugger könnte ich Ihnen nicht genau sagen, was Ihre Besetzung NSDictionarytun soll, aber der Fehler, den Sie sehen, ist, weil er dict!["currently"]!Typ hatAny

Wie lösen Sie das? Ich gehe davon aus, dass dict!["currently"]!es sich um ein Wörterbuch handelt, und Sie haben viele Möglichkeiten:

Zuerst könnten Sie so etwas tun:

let currentConditionsDictionary: [String: AnyObject] = dict!["currently"]! as! [String: AnyObject]  

Dadurch erhalten Sie ein Wörterbuchobjekt, das Sie dann nach Werten abfragen und so Ihre Temperatur wie folgt ermitteln können:

let currentTemperatureF = currentConditionsDictionary["temperature"] as! Double

Oder wenn Sie es vorziehen, können Sie es in der Linie tun:

let currentTemperatureF = (dict!["currently"]! as! [String: AnyObject])["temperature"]! as! Double

Hoffentlich hilft das, ich fürchte, ich hatte keine Zeit, eine Beispiel-App zu schreiben, um sie zu testen.

Ein letzter Hinweis: [String: AnyObject]Am einfachsten ist es, die JSON-Nutzdaten gleich zu Beginn einfach zu übertragen .

let parsedData = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as! Dictionary<String, AnyObject>

dict!["currently"]! as! [String: String]wird abstürzen
vadian

Der Punkt, an dem es abstürzte, war die ["Temperatur"] !! und auch versuchen, String in NSString umzuwandeln - überprüft, dass die neue Lösung funktioniert swiftlang.ng.bluemix.net/#/repl/57d3bc683a422409bf36c391
discorevilo

[String: String]kann überhaupt nicht funktionieren, da es einige numerische Werte gibt. Es funktioniert nicht in einem Mac Playground
vadian

@vadian ah, ja ich hatte diese nicht bemerkt und der schnelle Sandkasten versteckte sie hilfreich! - Jetzt [noch einmal] korrigiert (und unter macOS getestet). Vielen Dank für den Hinweis :)
discorevilo

6
let str = "{\"names\": [\"Bob\", \"Tim\", \"Tina\"]}"

let data = str.data(using: String.Encoding.utf8, allowLossyConversion: false)!

do {
    let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject]
    if let names = json["names"] as? [String] 
{
        print(names)
}
} catch let error as NSError {
    print("Failed to load: \(error.localizedDescription)")
}

5

Ich habe quicktype genau für diesen Zweck erstellt. Fügen Sie einfach Ihren Beispiel-JSON ein und quicktype generiert diese Typhierarchie für Ihre API-Daten:

struct Forecast {
    let hourly: Hourly
    let daily: Daily
    let currently: Currently
    let flags: Flags
    let longitude: Double
    let latitude: Double
    let offset: Int
    let timezone: String
}

struct Hourly {
    let icon: String
    let data: [Currently]
    let summary: String
}

struct Daily {
    let icon: String
    let data: [Datum]
    let summary: String
}

struct Datum {
    let precipIntensityMax: Double
    let apparentTemperatureMinTime: Int
    let apparentTemperatureLowTime: Int
    let apparentTemperatureHighTime: Int
    let apparentTemperatureHigh: Double
    let apparentTemperatureLow: Double
    let apparentTemperatureMaxTime: Int
    let apparentTemperatureMax: Double
    let apparentTemperatureMin: Double
    let icon: String
    let dewPoint: Double
    let cloudCover: Double
    let humidity: Double
    let ozone: Double
    let moonPhase: Double
    let precipIntensity: Double
    let temperatureHigh: Double
    let pressure: Double
    let precipProbability: Double
    let precipIntensityMaxTime: Int
    let precipType: String?
    let sunriseTime: Int
    let summary: String
    let sunsetTime: Int
    let temperatureMax: Double
    let time: Int
    let temperatureLow: Double
    let temperatureHighTime: Int
    let temperatureLowTime: Int
    let temperatureMin: Double
    let temperatureMaxTime: Int
    let temperatureMinTime: Int
    let uvIndexTime: Int
    let windGust: Double
    let uvIndex: Int
    let windBearing: Int
    let windGustTime: Int
    let windSpeed: Double
}

struct Currently {
    let precipProbability: Double
    let humidity: Double
    let cloudCover: Double
    let apparentTemperature: Double
    let dewPoint: Double
    let ozone: Double
    let icon: String
    let precipIntensity: Double
    let temperature: Double
    let pressure: Double
    let precipType: String?
    let summary: String
    let uvIndex: Int
    let windGust: Double
    let time: Int
    let windBearing: Int
    let windSpeed: Double
}

struct Flags {
    let sources: [String]
    let isdStations: [String]
    let units: String
}

Außerdem wird ein abhängigkeitsfreier Marshalling-Code generiert, um den Rückgabewert von JSONSerialization.jsonObjectin a zu locken Forecast, einschließlich eines praktischen Konstruktors, der eine JSON-Zeichenfolge verwendet, damit Sie schnell einen stark typisierten ForecastWert analysieren und auf seine Felder zugreifen können:

let forecast = Forecast.from(json: jsonString)!
print(forecast.daily.data[0].windGustTime)

Sie können quicktype von npm mit installieren npm i -g quicktypeoder die Web-Benutzeroberfläche verwenden , um den vollständig generierten Code zum Einfügen in Ihren Spielplatz zu erhalten.


Die Links schlagen fehl.
zeichnete ..

Fantastische Zeitersparnis! Gut gemacht!
Marko

1
Geniales Werkzeug. Vielen Dank.
Ahmet Ardal

4

Aktualisiert das isConnectToNetwork-Functiondanach dank dieses Beitrags .

Ich habe eine zusätzliche Methode dafür geschrieben:

import SystemConfiguration

func loadingJSON(_ link:String, postString:String, completionHandler: @escaping (_ JSONObject: AnyObject) -> ()) {

    if(isConnectedToNetwork() == false){
        completionHandler("-1" as AnyObject)
        return
    }

    let request = NSMutableURLRequest(url: URL(string: link)!)
    request.httpMethod = "POST"
    request.httpBody = postString.data(using: String.Encoding.utf8)

    let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
        guard error == nil && data != nil else { // check for fundamental networking error
            print("error=\(error)")
            return
        }

        if let httpStatus = response as? HTTPURLResponse , httpStatus.statusCode != 200 { // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }
        //JSON successfull
        do {
            let parseJSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
            DispatchQueue.main.async(execute: {
                completionHandler(parseJSON as AnyObject)
            });
        } catch let error as NSError {
            print("Failed to load: \(error.localizedDescription)")
        }
    }
    task.resume()
}

func isConnectedToNetwork() -> Bool {

    var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)

    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }

    var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
    if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
        return false
    }

    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
    let ret = (isReachable && !needsConnection)

    return ret
}

Jetzt können Sie dies ganz einfach in Ihrer App aufrufen, wo immer Sie möchten

loadingJSON("yourDomain.com/login.php", postString:"email=\(userEmail!)&password=\(password!)") { parseJSON in

    if(String(describing: parseJSON) == "-1"){
        print("No Internet")
    } else {

    if let loginSuccessfull = parseJSON["loginSuccessfull"] as? Bool {
        //... do stuff
    }
}

Marco, was wäre der beste Weg, um diese Funktion in das Projekt aufzunehmen? in einem Contorller oder Modell?
KamalPanhwar

hey, du fügst einfach die erste Methode func loadJSON (...) in eine extra schnelle Datei oder Klasse ein. Danach können Sie dies von jedem Controller in Ihrem Projekt aus aufrufen
Marco Weber

Ich habe es versucht, aber ich liebe die Idee, eine vollständige Lösung zu demonstrieren und auch, wie man sie einschließlich der Hilfsmethode isConnectedToNetwork () verwendet. Ich habe die Idee, wie man sie wahrscheinlich in gutem Code implementiert
Amr Angry

Also habe ich einfach eine neue Swift-Datei verwendet (linker Klick auf Ihren Projektbaum, neue Datei ..., Swift-Datei) und sie jsonhelper.swift genannt. In dieser Datei platzieren Sie den ersten Code, loadJSON () und isConnectedToNetwork (). Danach können Sie diese beiden Funktionen in jedem Teil Ihres Projekts verwenden. Wenn Sie beispielsweise in einer loginVC als Aktion der Anmeldeschaltfläche den zweiten Code verwenden können, müssen Sie natürlich die Domäne, die Post-Zeichenfolge und die paseJson-Werte (parseJSON ["loginSuccessfull"]) ändern, damit sie übereinstimmen Ihre PHP-Datei
Marco Weber

0

Swift hat eine mächtige Typinferenz. Lassen Sie uns die Kesselplatte "if let" oder "guard let" loswerden und das Auspacken mit einem funktionalen Ansatz erzwingen:

  1. Hier ist unser JSON. Wir können optional JSON oder üblich verwenden. Ich verwende optional in unserem Beispiel:

    let json: Dictionary<String, Any>? = ["current": ["temperature": 10]]
  1. Hilfsfunktionen. Wir müssen sie nur einmal schreiben und dann mit jedem Wörterbuch wiederverwenden:

    /// Curry
    public func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> (A) -> (B) -> C {
        return { a in
            { f(a, $0) }
        }
    }

    /// Function that takes key and optional dictionary and returns optional value
    public func extract<Key, Value>(_ key: Key, _ json: Dictionary<Key, Any>?) -> Value? {
        return json.flatMap {
            cast($0[key])
        }
    }

    /// Function that takes key and return function that takes optional dictionary and returns optional value
    public func extract<Key, Value>(_ key: Key) -> (Dictionary<Key, Any>?) -> Value? {
        return curry(extract)(key)
    }

    /// Precedence group for our operator
    precedencegroup RightApplyPrecedence {
        associativity: right
        higherThan: AssignmentPrecedence
        lowerThan: TernaryPrecedence
    }

    /// Apply. g § f § a === g(f(a))
    infix operator § : RightApplyPrecedence
    public func §<A, B>(_ f: (A) -> B, _ a: A) -> B {
        return f(a)
    }

    /// Wrapper around operator "as".
    public func cast<A, B>(_ a: A) -> B? {
        return a as? B
    }
  1. Und hier ist unsere Magie - extrahieren Sie den Wert:

    let temperature = (extract("temperature") § extract("current") § json) ?? NSNotFound

Nur eine Codezeile und kein gewaltsames Auspacken oder manuelles Gießen. Dieser Code funktioniert auf dem Spielplatz, sodass Sie ihn kopieren und überprüfen können. Hier ist eine Implementierung auf GitHub.


0

Dies ist ein anderer Weg, um Ihr Problem zu lösen. Schauen Sie sich also bitte die folgende Lösung an. Hoffe es wird dir helfen.

let str = "{\"names\": [\"Bob\", \"Tim\", \"Tina\"]}"
let data = str.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do {
    let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject]
    if let names = json["names"] as? [String] {
        print(names)
    }
} catch let error as NSError {
    print("Failed to load: \(error.localizedDescription)")
}

0

Das Problem liegt in der API-Interaktionsmethode. Die JSON-Analyse wird nur in der Syntax geändert. Das Hauptproblem ist das Abrufen von Daten. Was Sie verwenden, ist eine synchrone Methode zum Abrufen von Daten. Das funktioniert nicht in jedem Fall. Was Sie verwenden sollten, ist eine asynchrone Methode zum Abrufen von Daten. Auf diese Weise müssen Sie Daten über die API anfordern und warten, bis sie mit Daten antworten. Sie können dies mit URL-Sitzungen und Bibliotheken von Drittanbietern wie erreichen Alamofire. Unten finden Sie den Code für die URL-Sitzungsmethode.

let urlString = "https://api.forecast.io/forecast/apiKey/37.5673776,122.048951"
let url = URL.init(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
    guard error == nil else {
        print(error)
    }
    do {
        let Data = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
        // Note if your data is coming in Array you should be using [Any]()
        //Now your data is parsed in Data variable and you can use it normally
        let currentConditions = Data["currently"] as! [String:Any]
        print(currentConditions)
        let currentTemperatureF = currentConditions["temperature"] as! Double
        print(currentTemperatureF)
    } catch let error as NSError {
        print(error)
    }
}.resume()

0
{
    "User":[
      {
        "FirstUser":{
        "name":"John"
        },
       "Information":"XY",
        "SecondUser":{
        "name":"Tom"
      }
     }
   ]
}

Wenn ich ein Modell mit dem vorherigen json erstelle Verwenden Sie diesen Link [Blog]: http://www.jsoncafe.com , um eine codierbare Struktur oder ein beliebiges Format zu generieren

Modell

import Foundation
struct RootClass : Codable {
    let user : [Users]?
    enum CodingKeys: String, CodingKey {
        case user = "User"
    }

    init(from decoder: Decoder) throws {
        let values = try? decoder.container(keyedBy: CodingKeys.self)
        user = try? values?.decodeIfPresent([Users].self, forKey: .user)
    }
}

struct Users : Codable {
    let firstUser : FirstUser?
    let information : String?
    let secondUser : SecondUser?
    enum CodingKeys: String, CodingKey {
        case firstUser = "FirstUser"
        case information = "Information"
        case secondUser = "SecondUser"
    }
    init(from decoder: Decoder) throws {
        let values = try? decoder.container(keyedBy: CodingKeys.self)
        firstUser = try? FirstUser(from: decoder)
        information = try? values?.decodeIfPresent(String.self, forKey: .information)
        secondUser = try? SecondUser(from: decoder)
    }
}
struct SecondUser : Codable {
    let name : String?
    enum CodingKeys: String, CodingKey {
        case name = "name"
    }
    init(from decoder: Decoder) throws {
        let values = try? decoder.container(keyedBy: CodingKeys.self)
        name = try? values?.decodeIfPresent(String.self, forKey: .name)
    }
}
struct FirstUser : Codable {
    let name : String?
    enum CodingKeys: String, CodingKey {
        case name = "name"
    }
    init(from decoder: Decoder) throws {
        let values = try? decoder.container(keyedBy: CodingKeys.self)
        name = try? values?.decodeIfPresent(String.self, forKey: .name)
    }
}

Analysieren

    do {
        let res = try JSONDecoder().decode(RootClass.self, from: data)
        print(res?.user?.first?.firstUser?.name ?? "Yours optional value")
    } catch {
        print(error)
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.