JSON'u Swift 3'te Doğru Bir Şekilde Ayrıştırma


123

Bir JSON yanıtı almaya ve sonuçları bir değişkende saklamaya çalışıyorum. Bu kodun sürümleri Swift'in önceki sürümlerinde Xcode 8'in GM sürümü piyasaya sürülene kadar çalışıyordu. StackOverflow'da birkaç benzer gönderiye göz attım : Swift 2 Ayrıştırma JSON - Swift 3'te 'AnyObject' ve JSON Ayrıştırma türünde bir değere abone olamaz .

Ancak, orada iletilen fikirlerin bu senaryoda geçerli olmadığı görülüyor.

Swift 3'te JSON yanıtını nasıl doğru bir şekilde ayrıştırırım? Swift 3'te JSON'un okunma biçiminde bir şey değişti mi?

Söz konusu kod aşağıdadır (bir oyun alanında çalıştırılabilir):

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

Düzenleme: Aşağıda, API çağrısından sonra elde edilen sonuçların bir örneğidir.print(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]

API çağrınızdan dönen örnek verileri koyabilir misiniz?
Kullanıcı

1
Evet, baskıdan sonra yazdırılan sonuçların bir örneğini ekledim (currentConditions). Umarım yardımcı olur.
user2563039

Json'u swift4'te Kodlanabilir protokolü kullanarak ayrıştırın stackoverflow.com/a/52931265/9316566
Naser Mohamed

Yanıtlar:


172

Her şeyden önce hiçbir zaman uzak bir URL'den eşzamanlı olarak veri yükleme , her zaman gibi eşzamansız yöntemler kullanın URLSession.

"Herhangi biri" nin alt simge üyesi yoktur

derleyicinin ara nesnelerin (örneğin currentlyiçinde ["currently"]!["temperature"]) ne tür olduğuna dair hiçbir fikri olmadığı ve Foundation koleksiyon türlerini şu şekilde kullandığınız için oluşur.NSDictionary hakkında hiçbir fikri olmadığı ve derleyici hakkında hiçbir fikri olmadığı için oluşur.

Ek olarak, Swift 3'te derleyiciye her şeyin türü hakkında bilgi vermek gerekir. abone olunan nesnelerin .

JSON serileştirmesinin sonucunu gerçek türe çevirmelisiniz.

Bu kod kullanımları URLSessionve münhasıran Swift yerli türleri

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

Tüm anahtar / değer çiftlerini yazdırmak için currentConditionsyazabilirsin

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

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

Aşağıdakilerle ilgili bir not jsonObject(with data:

Pek çok (hepsi görünüyor) öğretici .mutableContainersveya .mutableLeavesSwift'de tamamen saçma olan seçenekler öneriyor . İki seçenek, sonucu NSMutable...nesnelere atamak için kullanılan eski Objective-C seçenekleridir . varSwift'de herhangi bir iable varsayılan olarak değiştirilebilir ve bu seçeneklerden herhangi birini geçirmenin ve sonucu bir letsabite atamanın hiçbir etkisi yoktur. Dahası, uygulamaların çoğu zaten serileştirilmemiş JSON'u asla değiştirmiyor.

Swift yararlıdır sadece (nadir) bir seçenektir .allowFragmentsJSON kök nesnesi, bir değer türü olabilir, eğer varsa gerekli olan ( String, Number, Boolveya null) ziyade toplama türlerinden biri ( arrayveya dictionary). Ancak normalde, seçenek yokoptions anlamına gelen parametreyi atlayın .

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

JSON'u ayrıştırmak için bazı genel hususlar

JSON, iyi düzenlenmiş bir metin biçimidir. Bir JSON dizesini okumak çok kolaydır. Dizeyi dikkatlice okuyun . Yalnızca altı farklı tür vardır - iki koleksiyon türü ve dört değer türü.


Koleksiyon türleri

  • Dizi - JSON: köşeli parantez içindeki nesneler []- Swift: [Any]ancak çoğu durumda[[String:Any]]
  • Sözlük - JSON: kaşlı ayraçlar içindeki nesneler {}- Swift:[String:Any]

Değer türleri

  • Dize - JSON: çift tırnak herhangi bir değer "Foo", hatta "123"ya "false"- Swift:String
  • Sayı - JSON: çift ​​tırnak içinde olmayan sayısal değerler 123veya 123.0- Swift: IntveyaDouble
  • Bool - JSON: trueveya çift ​​tırnak içinde false değil - Swift: trueveyafalse
  • null - JSON: null- Swift:NSNull

JSON belirtimine göre sözlüklerdeki tüm anahtarların olması gerekir String.


Temel olarak, isteğe bağlı bağları güvenli bir şekilde açmak için her zaman isteğe bağlı bağlamaların kullanılması önerilir

Kök nesne bir sözlükse ( {}), türü[String:Any]

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

ve değerleri anahtarlara göre alın ( OneOfSupportedJSONTypesyukarıda açıklandığı gibi JSON koleksiyonu veya değer türüdür.)

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

Kök nesne bir dizi ise ( []), türü[[String:Any]]

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

ve dizi boyunca yineleyin

for item in parsedData {
    print(item)
}

Belirli bir dizinde bir öğeye ihtiyacınız varsa, dizinin mevcut olup olmadığını da kontrol edin

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

JSON'un bir koleksiyon türü yerine sadece değer türlerinden biri olduğu nadir durumlarda, .allowFragmentsseçeneği iletmeniz ve sonucu uygun değer türüne çevirmeniz gerekir, örneğin

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

Apple, Swift Blog'da kapsamlı bir makale yayınladı: Swift'de JSON ile Çalışma


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

Swift 4 + 'da Codableprotokol, JSON'u doğrudan yapılara / sınıflara ayrıştırmak için daha uygun bir yol sağlar.

Örneğin, soruda verilen JSON örneği (biraz değiştirildi)

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

yapının kodu çözülebilir Weather. Swift türleri yukarıda açıklananlarla aynıdır. Birkaç ek seçenek var:

  • Bir'yi temsil eden dizelerin URLkodu doğrudan URL.
  • timeTam sayı olarak deşifre edilebilir Dateile dateDecodingStrategy .secondsSince1970.
  • snaked_cased JSON tuşları dönüştürülebilir CamelCase ilekeyDecodingStrategy .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)
}

Diğer Kodlanabilir kaynaklar:


Bu çok yardımcı. Sadece yukarıdaki kodun oyun alanında çalıştırıldığında neden görünür çıktı göstermediğini merak ediyorum.
user2563039

Yukarıda belirtildiği gibi dict!["currently"]!, derleyicinin sonraki anahtar aboneliğini güvenli bir şekilde çıkarabileceği bir sözlüğün belirsiz sonucunu çevirmeniz gerekir.
vadian

1
Apple makalesi oldukça havalı, ancak nedense onu hızlı 3 ile çalıştırmayı başaramadım. Type [String: Any] hakkında şikayet ediyor mu? alt simge üyesi yok. Onunla ilgili başka sorunlar da vardı, ancak üstesinden gelebildim. Kimsenin kodunun gerçekten çalışan bir örneği var mı?
Shades

@Shades Bir soru sorun ve kodunuzu gönderin. Sorununuz büyük olasılıkla paketlenmemiş isteğe bağlı seçeneklerle ilgilidir.
vadian

API çağrınızdan dönen örnek verileri koyabilir misiniz?
Kullanıcı

12

Swift 3 Xcode 8 Beta 6 ile oldu büyük bir değişim olarak bu kimliği şimdi ithalatı AnyyerineAnyObject .

Bu parsedData, büyük olasılıkla türle birlikte bir sözlük olarak döndürüldüğü anlamına gelir [Any:Any]. Bir hata ayıklayıcı kullanmadan, oyuncu kadronuzun ne yapacağını tam olarak söyleyemezdim NSDictionary, ancak gördüğünüz hatanın nedenidict!["currently"]! türü vardırAny

Peki bunu nasıl çözeceksiniz? Referans verdiğiniz yoldan, varsayıyorumdict!["currently"]! , bir sözlük ve bu nedenle birçok seçeneğiniz var:

İlk önce bunun gibi bir şey yapabilirsiniz:

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

Bu size, daha sonra değerler için sorgulayabileceğiniz ve böylece sıcaklığınızı şu şekilde alabileceğiniz bir sözlük nesnesi verecektir:

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

Ya da isterseniz, sırayla yapabilirsiniz:

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

Umarım bu yardımcı olur, korkarım test etmek için örnek bir uygulama yazmaya zamanım olmadı.

Son bir not: Yapılması en kolay şey, JSON yükünü [String: AnyObject]başlangıçta doğrudan doğruya aktarmak olabilir .

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

dict!["currently"]! as! [String: String]çökecek
vadian

Düştüğü nokta ["sıcaklık"] idi !! ve ayrıca String'i NSString'e aktarmaya
discorevilo

[String: String]hiç çalışamaz çünkü birkaç sayısal değer vardır. Mac Playground'da çalışmıyor
vadian

@vadian ah, evet bunları fark etmemiştim ve hızlı sanal alan onları yardımcı bir şekilde sakladı! - Şimdi [bir kez daha] düzeltildi (ve macOS'ta test edildi). Bunu işaret ettiğiniz için teşekkür ederiz :)
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

Ben inşa QuickType bu amaç için kesinlikle. Örnek JSON'nuzu yapıştırmanız yeterlidir ve quicktype, API verileriniz için bu tür hiyerarşisini oluşturur:

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
}

Aynı zamanda dönüş değerini koaksiyel bağımlılık içermeyen sıralama kodu üretir JSONSerialization.jsonObjectbir içine Forecasthızla kesinlikle yazılı ayrıştırmak böylece bir JSON dizesi götüren bir kolaylık kurucu da dahil, Forecastdeğeri ve onun alanlarını erişmek:

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

Quicktype'ı npm'den kurabilir npm i -g quicktypeveya oyun alanınıza yapıştırmak üzere oluşturulan kodun tamamını almak için web kullanıcı arayüzünü kullanabilirsiniz .


Bağlantılar kopuyor.
çizdi ..

Harika zaman tasarrufu! Aferin!
marko

1
Harika bir araç. Teşekkürler.
Ahmet Ardal

4

GüncelisConnectToNetwork-Function Buna sonradan sayesinde yazı .

Bunun için ekstra bir yöntem yazdım:

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
}

Artık bunu uygulamanızda istediğiniz yerde kolayca arayabilirsiniz

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, bu işlevi projeye eklemenin en iyi yolu nedir? herhangi bir contorller veya modelde?
KamalPanhwar

hey, sadece ekstra hızlı bir dosyaya veya sınıfa ilk yöntemi func loadingJSON (...) ekleyin. Bundan sonra, projenizdeki her kontrolörden buna çağrı yapabilirsiniz
Marco Weber

denedim, ancak tam bir çözüm gösterme fikrini ve ayrıca yardımcı yöntem dahil olmak üzere nasıl kullanılacağını seviyorum isConnectedToNetwork () bu muhtemelen iyi bir kodda nasıl uygulanacağına dair bir fikir
Amr Angry

bu yüzden yeni bir hızlı dosya kullandım (proje ağacınızda sol tıklama, yeni dosya ..., hızlı dosya) ve ona jsonhelper.swift adını verdim. bu dosyaya ilk kodu, loadingJSON () ve isConnectedToNetwork () yerleştirirsiniz. bundan sonra bu iki işlevi projenizin her bölümünde kullanabilirsiniz. örneğin bir loginVC'de, oturum açma düğmesinin bir eylemi olarak ikinci kodu kullanabilirsiniz, açıkça etki alanını, gönderi dizesini ve paseJson değerlerini (parseJSON ["loginSuccessfull"]) eşleşecek şekilde değiştirmeniz gerekir. php dosyanız
Marco Weber

0

Swift'in güçlü bir tür çıkarımı var. İşlevsel yaklaşımı kullanarak "eğer izin verirseniz" veya "izin verirseniz" standart şablonundan kurtulalım ve açmaları zorlayalım:

  1. İşte JSON'umuz. İsteğe bağlı JSON veya normal kullanabiliriz. Örneğimizde isteğe bağlı kullanıyorum:

    let json: Dictionary<String, Any>? = ["current": ["temperature": 10]]
  1. Yardımcı fonksiyonlar. Bunları yalnızca bir kez yazmamız ve ardından herhangi bir sözlükle yeniden kullanmamız gerekir:

    /// 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. Ve işte sihrimiz - değeri çıkarın:

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

Sadece bir satır kod ve zorla açma veya manuel tip atama yok. Bu kod oyun alanında çalışır, böylece kopyalayıp kontrol edebilirsiniz. İşte bir uygulama GitHub'da .


0

Bu, probleminizi çözmenin başka bir yoludur. Bu yüzden lütfen aşağıdaki çözüme göz atın. Umarım size yardımcı olur.

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

Sorun API etkileşim yöntemiyle ilgilidir. JSON ayrıştırması yalnızca sözdiziminde değiştirilir. Asıl sorun, veri alma yöntemiyle ilgilidir. Kullandığınız şey, verileri almanın senkronize bir yoludur. Bu her durumda işe yaramıyor. Kullanmanız gereken şey, veri getirmenin eşzamansız bir yoludur. Bu şekilde, API üzerinden veri talep etmeniz ve veri ile yanıt vermesini beklemeniz gerekir. Bunu URL oturumu ve gibi üçüncü taraf kitaplıkları ile başarabilirsiniz Alamofire. URL Oturumu yönteminin kodu aşağıdadır.

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

Önceki json kullanarak model oluşturursam Bu bağlantıyı kullanarak [blog]: http://www.jsoncafe.com Kodlanabilir yapı veya Herhangi Bir Format oluşturmak için

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

Ayrıştırma

    do {
        let res = try JSONDecoder().decode(RootClass.self, from: data)
        print(res?.user?.first?.firstUser?.name ?? "Yours optional value")
    } catch {
        print(error)
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.