Mengurai JSON dengan benar di Swift 3

123

Saya mencoba mengambil respons JSON dan menyimpan hasilnya dalam variabel. Saya memiliki versi kode ini yang berfungsi di rilis Swift sebelumnya, hingga versi GM dari Xcode 8 dirilis. Saya telah melihat beberapa posting serupa di StackOverflow: Swift 2 Parsing JSON - Tidak dapat menggunakan nilai tipe 'AnyObject' dan JSON Parsing di Swift 3 .

Namun, tampaknya gagasan yang disampaikan di sana tidak berlaku untuk skenario ini.

Bagaimana cara mengurai respons JSON dengan benar di Swift 3? Apakah ada yang berubah dalam cara JSON dibaca di Swift 3?

Di bawah ini adalah kode yang dimaksud (dapat dijalankan di taman bermain):

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)")
        }
    }
}

Edit: Berikut adalah contoh hasil dari panggilan API setelahnyaprint(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]
pengguna2563039
sumber
Dapatkah Anda menempatkan data sampel yang dikembalikan dari panggilan API Anda?
Pengguna
1
Ya, saya baru saja menambahkan contoh hasil yang dicetak setelah dicetak (currentConditions). Semoga membantu.
pengguna2563039
Parse json di swift4 menggunakan protokol yang dapat dikodekan stackoverflow.com/a/52931265/9316566
Naser Mohamed

Jawaban:

172

Pertama-tama jangan pernah memuat data secara sinkron dari URL jarak jauh , gunakan selalu metode asinkron seperti URLSession.

'Any' tidak memiliki anggota subskrip

terjadi karena kompilator tidak tahu jenis objek perantara (misalnya currentlydalam ["currently"]!["temperature"]) dan karena Anda menggunakan tipe kumpulan Foundation seperti NSDictionarykompilator tidak tahu sama sekali tentang tipe tersebut.

Selain itu di Swift 3, Anda perlu memberi tahu kompiler tentang tipe semua objek yang disubscribe.

Anda harus mentransmisikan hasil serialisasi JSON ke tipe sebenarnya.

Kode ini menggunakan URLSessiondan tipe asli Swift secara eksklusif

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()

Untuk mencetak semua pasangan kunci / nilai currentConditionsAnda dapat menulis

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

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

Catatan tentang jsonObject(with data:

Banyak (sepertinya semua) tutorial menyarankan .mutableContainersatau .mutableLeavesopsi yang benar-benar tidak masuk akal di Swift. Kedua opsi tersebut adalah opsi Objective-C warisan untuk menetapkan hasil ke NSMutable...objek. Di Swift, variable apa pun dapat berubah secara default dan meneruskan salah satu opsi tersebut dan menetapkan hasilnya ke letkonstanta tidak berpengaruh sama sekali. Lebih jauh lagi, sebagian besar implementasi tidak pernah memutasi JSON yang telah dideserialisasi.

Satu-satunya (jarang) pilihan yang berguna di Swift adalah .allowFragmentsyang diperlukan jika jika JSON akar objek bisa menjadi jenis nilai ( String, Number, Boolatau null) bukan salah satu jenis koleksi ( arrayatau dictionary). Tetapi biasanya menghilangkan optionsparameter yang berarti Tidak ada opsi .

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

Beberapa pertimbangan umum untuk mengurai JSON

JSON adalah format teks yang tersusun rapi. Sangat mudah untuk membaca string JSON. Baca string dengan cermat . Hanya ada enam tipe berbeda - dua tipe koleksi dan empat tipe nilai.


Jenis koleksinya adalah

  • Array - JSON: objek dalam tanda kurung siku []- Swift: [Any]tetapi dalam banyak kasus[[String:Any]]
  • Kamus - JSON: objek dalam kurung kurawal {}- Swift:[String:Any]

Jenis nilainya adalah

  • String - JSON: nilai apa pun dalam tanda kutip ganda "Foo", genap "123"atau "false"- Swift:String
  • Angka - JSON: nilai numerik tidak dalam tanda kutip ganda 123atau 123.0- Swift: IntatauDouble
  • Bool - JSON: trueatau false tidak dalam tanda kutip ganda - Swift: trueataufalse
  • null - JSON: null- Swift:NSNull

Menurut spesifikasi JSON, semua kunci dalam kamus harus ada String.


Pada dasarnya, selalu disarankan untuk menggunakan binding opsional untuk membuka bungkus opsional dengan aman

Jika objek root adalah dictionary ( {}), gunakan tipe tersebut[String:Any]

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

dan mengambil nilai dengan kunci dengan ( OneOfSupportedJSONTypesbaik koleksi JSON atau tipe nilai seperti yang dijelaskan di atas.)

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

Jika objek root adalah array ( []) gunakan tipe[[String:Any]]

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

dan melakukan iterasi melalui array dengan

for item in parsedData {
    print(item)
}

Jika Anda membutuhkan item pada indeks tertentu, periksa juga apakah indeks tersebut ada

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

Dalam kasus yang jarang terjadi, JSON hanyalah salah satu jenis nilai - bukan jenis koleksi - Anda harus meneruskan .allowFragmentsopsi dan mentransmisikan hasilnya ke jenis nilai yang sesuai, misalnya

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

Apple telah menerbitkan artikel komprehensif di Swift Blog: Working with JSON in Swift


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

Di Swift 4+, Codableprotokol menyediakan cara yang lebih mudah untuk mengurai JSON langsung ke dalam struct / kelas.

Misalnya contoh JSON yang diberikan dalam pertanyaan (sedikit diubah)

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

dapat diterjemahkan ke dalam struct Weather. Jenis Swift sama seperti yang dijelaskan di atas. Ada beberapa opsi tambahan:

  • String yang merepresentasikan sebuah URLdapat diterjemahkan secara langsung sebagai URL.
  • The timeinteger dapat diterjemahkan sebagai Datedengan dateDecodingStrategy .secondsSince1970.
  • kunci JSON snaked_cased dapat diubah menjadi camelCase dengankeyDecodingStrategy .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)
}

Sumber Berkode lainnya:

vadian
sumber
Ini sangat membantu. Saya hanya ingin tahu mengapa kode di atas tidak menunjukkan output yang terlihat saat dijalankan di taman bermain.
pengguna2563039
Seperti disebutkan di atas, Anda perlu mentransmisikan hasil ambigu dari dict!["currently"]!kamus agar compiler dapat menyimpulkan langganan kunci berikutnya dengan aman.
vadian
1
Artikel Apple cukup keren, tetapi saya tidak bisa menjalankannya dengan swift 3 karena beberapa alasan. Ini mengeluh tentang Type [String: Any]? tidak memiliki anggota subskrip. Ada beberapa masalah lain dengannya juga, tetapi saya bisa mengatasinya. Adakah yang punya contoh kode mereka yang benar-benar berjalan?
Shades
@Shades Ajukan pertanyaan dan posting kode Anda. Kemungkinan besar masalah Anda terkait dengan opsional yang terbuka.
vadian
Dapatkah Anda menempatkan data sampel yang dikembalikan dari panggilan API Anda?
Pengguna
12

Perubahan besar yang terjadi dengan Xcode 8 Beta 6 untuk Swift 3 adalah bahwa id sekarang mengimpor Anydaripada AnyObject.

Ini berarti yang parsedDatadikembalikan sebagai kamus kemungkinan besar dengan tipe [Any:Any]. Tanpa menggunakan debugger saya tidak dapat memberi tahu Anda dengan tepat apa yang NSDictionaryakan dilakukan cast Anda, tetapi kesalahan yang Anda lihat adalah karena dict!["currently"]!memiliki tipeAny

Jadi, bagaimana Anda mengatasi ini? Dari cara Anda mereferensikannya, saya berasumsi bahwa itu dict!["currently"]!adalah kamus sehingga Anda memiliki banyak pilihan:

Pertama, Anda dapat melakukan sesuatu seperti ini:

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

Ini akan memberi Anda objek kamus yang kemudian dapat Anda kueri nilai-nilainya sehingga Anda bisa mendapatkan suhu seperti ini:

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

Atau jika Anda lebih suka, Anda dapat melakukannya sejalan:

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

Semoga ini membantu, saya khawatir saya belum sempat menulis aplikasi sampel untuk mengujinya.

Satu catatan terakhir: hal termudah untuk dilakukan, mungkin cukup dengan memasukkan muatan JSON ke dalamnya [String: AnyObject]tepat di awal.

let parsedData = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as! Dictionary<String, AnyObject>
discorevilo
sumber
dict!["currently"]! as! [String: String]akan crash
vadian
Titik di mana ia jatuh adalah ["suhu"] !! dan juga mencoba mentransmisikan String ke NSString - memverifikasi solusi baru berfungsi swiftlang.ng.bluemix.net/#/repl/57d3bc683a422409bf36c391
discorevilo
[String: String]tidak bisa bekerja sama sekali karena ada beberapa nilai numerik. Tidak berfungsi di Mac Playground
vadian
@vadian ah, ya saya tidak memperhatikan itu dan kotak pasir yang cepat menyembunyikannya dengan sangat membantu! - Dikoreksi [sekali lagi] sekarang (dan diuji di macOS). Terima kasih telah menunjukkan hal ini :)
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)")
}
BhuShan PaWar
sumber
5

Saya membuat quicktype persis untuk tujuan ini. Cukup tempelkan sampel JSON Anda dan quicktype menghasilkan hierarki jenis ini untuk data API Anda:

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
}

Ini juga menghasilkan kode marshaling bebas ketergantungan untuk membujuk nilai kembalian JSONSerialization.jsonObjectmenjadi a Forecast, termasuk konstruktor praktis yang mengambil string JSON sehingga Anda dapat dengan cepat mengurai nilai yang sangat diketik Forecastdan mengakses bidangnya:

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

Anda dapat menginstal quicktype dari npm dengan npm i -g quicktypeatau menggunakan UI web untuk mendapatkan kode lengkap yang dibuat untuk ditempelkan ke taman bermain Anda.

David Siegel
sumber
Tautan gagal.
diundi ..
Penghemat waktu yang fantastis! Kerja bagus!
marko
1
Alat yang brilian. Terima kasih.
Ahmet Ardal
4

Diperbarui yang isConnectToNetwork-Functionsetelah itu, berkat ini posting .

Saya menulis metode tambahan untuk itu:

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
}

Jadi sekarang Anda dapat dengan mudah memanggil ini di aplikasi Anda di mana pun Anda mau

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 Weber
sumber
Marco, apa cara terbaik untuk menambahkan fungsi ini dalam proyek? di contorller atau model apa pun?
KamalPanhwar
hey, Anda cukup menambahkan metode pertama func loadingJSON (...) di file atau kelas ekstra cepat. Setelah itu Anda dapat memanggil ini dari setiap pengontrol dalam proyek Anda
Marco Weber
saya mencobanya, tetapi saya suka ide untuk mendemonstrasikan solusi lengkap dan juga bagaimana menggunakannya termasuk metode helper isConnectedToNetwork () itu saya ide tentang bagaimana menerapkannya mungkin dalam kode yang baik
Amr Angry
jadi saya baru saja menggunakan file swift baru (klik kiri pada pohon proyek Anda, file baru ..., file swift) dan menyebutnya jsonhelper.swift. dalam file ini Anda menempatkan kode pertama, loadingJSON () dan isConnectedToNetwork (). setelah itu Anda dapat menggunakan dua fungsi ini di setiap bagian proyek Anda. misalnya di loginVC, sebagai tindakan tombol login Anda dapat menggunakan kode kedua, jelas Anda harus mengubah domain, string posting dan nilai paseJson (parseJSON ["loginSuccessfull"]) agar cocok dengan file php Anda
Marco Weber
0

Swift memiliki inferensi tipe yang kuat. Mari singkirkan boilerplate "if let" atau "guard let" dan paksa pembongkaran menggunakan pendekatan fungsional:

  1. Inilah JSON kami. Kita bisa menggunakan JSON opsional atau biasa. Saya menggunakan opsional dalam contoh kami:

    let json: Dictionary<String, Any>? = ["current": ["temperature": 10]]
  1. Fungsi pembantu. Kita perlu menuliskannya hanya sekali dan kemudian menggunakannya kembali dengan kamus apa pun:

    /// 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. Dan inilah keajaiban kami - ekstrak nilainya:

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

Hanya satu baris kode dan tidak ada kekuatan yang dibuka atau casting tipe manual. Kode ini berfungsi di taman bermain, jadi Anda dapat menyalin dan memeriksanya. Berikut adalah implementasi di GitHub.

J. Doe
sumber
0

Ini adalah cara lain untuk menyelesaikan masalah Anda. Jadi silakan lihat solusi di bawah ini. Semoga bisa membantu Anda.

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)")
}
Olcay Ertaş
sumber
0

Masalahnya ada pada metode interaksi API. Penguraian JSON hanya diubah dalam sintaks. Masalah utamanya adalah dengan cara mengambil data. Apa yang Anda gunakan adalah cara sinkron untuk mendapatkan data. Ini tidak berhasil di setiap kasus. Yang harus Anda gunakan adalah cara asinkron untuk mengambil data. Dengan cara ini, Anda harus meminta data melalui API dan menunggunya merespons dengan data. Anda dapat mencapai ini dengan sesi URL dan perpustakaan pihak ketiga seperti Alamofire. Di bawah ini adalah kode untuk metode Sesi URL.

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()
Arun K
sumber
0
{
    "User":[
      {
        "FirstUser":{
        "name":"John"
        },
       "Information":"XY",
        "SecondUser":{
        "name":"Tom"
      }
     }
   ]
}

Jika saya membuat model menggunakan json sebelumnya Menggunakan tautan ini [blog]: http://www.jsoncafe.com untuk menghasilkan struktur yang Dapat Dikodekan atau Format Apa Pun

Model

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)
    }
}

Parse

    do {
        let res = try JSONDecoder().decode(RootClass.self, from: data)
        print(res?.user?.first?.firstUser?.name ?? "Yours optional value")
    } catch {
        print(error)
    }
Abishek T
sumber