web-dev-qa-db-fra.com

Analyse JSON dans Swift 3

Quelqu'un at-il réussi à trouver un moyen d’analyser les fichiers JSON dans Swift 3? J'ai pu récupérer les données mais je n'ai pas réussi à les décomposer en champs spécifiques. Je publierais un exemple de code, mais j’ai passé en revue de nombreuses méthodes différentes sans succès. Le format de base que je veux analyser ressemble à ceci. Merci d'avance.

{
  "Language": {

    "Field":[
          {
          "Number":"976",
          "Name":"Test"
          },
          {
          "Number":"977",
          "Name":"Test"
          }
       ]
   }
}
21
Nas5296

Avez-vous essayé JSONSerialization.jsonObject(with:options:)?

var jsonString = "{" +
    "\"Language\": {" +
    "\"Field\":[" +
    "{" +
    "\"Number\":\"976\"," +
    "\"Name\":\"Test\"" +
    "}," +
    "{" +
    "\"Number\":\"977\"," +
    "\"Name\":\"Test\"" +
    "}" +
    "]" +
    "}" +
    "}"

var data = jsonString.data(using: .utf8)!

let json = try? JSONSerialization.jsonObject(with: data)

Swift produit parfois une syntaxe très étrange.

if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
    print(number)
}

Tout ce qui se trouve dans la hiérarchie des objets JSON finit par être encapsulé de manière optionnelle (c'est-à-dire AnyObject?). Array<T> indice renvoie une variable T non facultative. Pour ce JSON, qui est encapsulé dans un indice optionnel, array retourne Optional<AnyObject>. Cependant, Dictionary<K, V> indice renvoie un Optional<V>. Pour ce JSON, l'indice renvoie le très étrange look Optional<Optional<AnyObject>> (c'est-à-dire AnyObject??).

  • json est un Optional<AnyObject>.
  • json?["Language"] renvoie un Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"] renvoie un Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0] renvoie un Optional<AnyObject>.
  • json?["Language"]??["Field"]??[0]?["Number"] renvoie un Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0]?["Number"] as? String renvoie un Optional<String>.

Le Optional<String> est ensuite utilisé par la syntaxe if let pour produire un String.


Note finale: l'itération du tableau de champs ressemble à ceci.

for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
    if let number = field["Number"] as? String {
        print(number)
    }
}

Swift 4 Update

Swift 4 rend tout cela beaucoup plus facile à gérer. Encore une fois, nous allons commencer avec vos données de test (""" rend cela beaucoup plus agréable).

let data = """
{
  "Language": {

    "Field":[
          {
          "Number":"976",
          "Name":"Test"
          },
          {
          "Number":"977",
          "Name":"Test"
          }
       ]
   }
}
""".data(using: .utf8)!

Ensuite, nous pouvons définir des classes autour des objets utilisés dans votre JSON.

struct Object: Decodable {
    let language: Language
    enum CodingKeys: String, CodingKey { case language="Language" }
}

struct Language: Decodable {
    let fields: [Field]
    enum CodingKeys: String, CodingKey { case fields="Field" }
}

struct Field: Decodable {
    let number: String
    let name: String
    enum CodingKeys: String, CodingKey { case number="Number"; case name="Name" }
}

L'énumération CodingKeys indique comment les propriétés de structure sont mappées aux chaînes de membre d'objet JSON. Ce mappage est fait automatiquement par Decodable.


L'analyse du JSON est maintenant simple.

let object = try! JSONDecoder().decode(Object.self, from: data)

print(object.language.fields[0].name)

for field in object.language.fields {
    print(field.number)
}
27
Jeffery Thomas

Dans Xcode 8 et Swift 3id importe maintenant comme Any plutôt que AnyObject

Cela signifie que JSONSerialization.jsonObject(with: data) renvoie Any. Vous devez donc convertir json data dans un type spécifique tel que [String:Any]. Il en va de même pour les champs suivants en aval du json.

var jsonString = "{" +
    "\"Language\": {" +
    "\"Field\":[" +
    "{" +
    "\"Number\":\"976\"," +
    "\"Name\":\"Test1\"" +
    "}," +
    "{" +
    "\"Number\":\"977\"," +
    "\"Name\":\"Test2\"" +
    "}" +
    "]" +
    "}" +
"}"

var data = jsonString.data(using: .utf8)!
if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
    let language = parsedData["Language"] as! [String:Any]
    print(language)
    let field = language["Field"] as! [[String:Any]]
    let name = field[0]["Name"]!
    print(name) // ==> Test1
}

En pratique, vous voudrez probablement qu'un champ spécifique soit enfoui dans le JSON. Supposons que c'est le champ Name du premier élément du tableau Field. Vous pouvez utiliser une chaîne de déroulements comme celle-ci pour accéder en toute sécurité au champ:

var data = jsonString.data(using: .utf8)!
if let json = try? JSONSerialization.jsonObject(with: data) as? [String:Any],
    let language = json?["Language"] as? [String:Any],
    let field = language["Field"] as? [[String:Any]],
    let name = field[0]["Name"] as? String, field.count > 0 {
    print(name) // ==> Test1
} else {
    print("bad json - do some recovery")
}

Vous pouvez également consulter le blog Swift d’Apple Travailler avec JSON dans Swift

13
serg_zhd

Pousser JSON manuellement dans une chaîne est un pita. Pourquoi ne pas simplement mettre le JSON dans un fichier et le lire?

Swift 3:

let bundle = Bundle(for: type(of: self))
    if let theURL = bundle.url(forResource: "response", withExtension: "json") {
        do {
            let data = try Data(contentsOf: theURL)
            if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
                grok(parsedData)
            }
        } catch {
            print(error)
        }
    }
3
Gene De Lisa

Utilisez la bibliothèque swiftjson Je pense que c’est un moyen très facile d’analyser 

let count: Int? = json["Field"].array?.count
            if let ct = count {

                for index in 0...ct-1{

                let number = json ["Field"][index]["number"].string
                let name = json ["Field"][index]["name"].string 

....

comme ça .

0
ismailtsn92

Analyse JSON avec Swift 4 de manière simple

   let url = URL(string: "http://mobileappdevelop.co/TIPIT/webservice/get_my_groups?user_id=5")
    URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
        guard let data = data, error == nil else { return }

        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]

             print(json)

            let posts =  json["Field"] as? [[String: Any]] ?? []
            print(posts)
        } catch let error as NSError {
            print(error)
        }

    }).resume()

}
0
user8771317
 override func viewDidLoad() {
        super.viewDidLoad()
        let url=URL(string:"http://api.androidhive.info/contacts/")
        do {
            let allContactsData = try Data(contentsOf: url!)
            let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
            if let arrJSON = allContacts["contacts"] {
                for index in 0...arrJSON.count-1 {
                    let aObject = arrJSON[index] as! [String : AnyObject]
                    names.append(aObject["name"] as! String)
                    contacts.append(aObject["email"] as! String)
                }
            }
            print(names)
            print(contacts)
            self.tableView.reloadData()
        }
        catch {
        }
    }
0
BhuShan PaWar

Analyse JSON dans Swift 4 à l'aide du protocole décodable:

Je crée un fichier mocky en utilisant votre objet json: 

http://www.mocky.io/v2/5a280c282f0000f92c0635e6

Voici le code pour analyser le JSON: 

Création de modèle:

import UIKit

struct Item : Decodable { 
// Properties must be the same name as specified in JSON , else it will return nil
var Number : String
var Name : String
}

struct Language : Decodable {
 var Field : [Item]
}

struct Result : Decodable {
 var Language : Language
}

Vous pouvez utiliser facultatif dans le modèle si vous n'êtes pas sûr qu'il manque quelque chose dans le fichier JSON.

C'est la logique d'analyse syntaxique:

class ViewController: UIViewController {

let url = "http://www.mocky.io/v2/5a280c282f0000f92c0635e6"

private func parseJSON() {

    guard let url = URL(string: url) else { return }

    let session = URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else { return }
        guard let result = try? JSONDecoder().decode(Result.self, from: data) else { return }
        print("\n\nResult : \(result)")
    }
    session.resume()
}

override func viewDidLoad() {
    super.viewDidLoad()
    parseJSON()
}
}

La sortie d'impression:

 Result : Result(Language: JSON_Parsing.Language(Field: [JSON_Parsing.Item(Number: "976", Name: "Test"), JSON_Parsing.Item(Number: "977", Name: "Test")]))

C'est le lien du projet github. Tu peux vérifier.

0
Ashis Laha