J'ai un fichier JSON, je veux analyser et utiliser une liste d'objets en vue tableau. Quelqu'un peut-il partager le code pour analyser le fichier JSON dans Swift?
Ne pourrait être plus simple:
import Foundation
var error: NSError?
let jsonData: NSData = /* get your json data */
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
Effectuer la demande d'API
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
Se préparer à la réponse
Déclarer un tableau comme ci-dessous
var data: NSMutableData = NSMutableData()
Recevoir la réponse
1.
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
// Received a new request, clear out the data object
self.data = NSMutableData()
}
2.
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
// Append the received chunk of data to our data object
self.data.appendData(data)
}
3.
func connectionDidFinishLoading(connection: NSURLConnection!) {
// Request complete, self.data should now hold the resulting info
// Convert the retrieved data in to an object through JSON deserialization
var err: NSError
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
if jsonResult.count>0 && jsonResult["results"].count>0 {
var results: NSArray = jsonResult["results"] as NSArray
self.tableData = results
self.appsTableView.reloadData()
}
}
Lorsque NSURLConnection reçoit une réponse, nous pouvons nous attendre à ce que la méthode didReceiveResponse soit appelée en notre nom. À ce stade, nous réinitialisons simplement nos données en disant self.data = NSMutableData (), créant ainsi un nouvel objet de données vide.
Une fois la connexion établie, nous commencerons à recevoir des données dans la méthode didReceiveData. L'argument de données transmis ici est la source de toutes nos informations juteuses. Nous devons conserver chaque bloc entrant, nous l'ajoutons donc à l'objet self.data que nous avons effacé plus tôt.
Enfin, lorsque la connexion est établie et que toutes les données ont été reçues, connectionDidFinishLoading est appelé et nous sommes prêts à utiliser les données dans notre application. Hourra!
La méthode connectionDidFinishLoading utilise la classe NSJSONSerialization pour convertir nos données brutes en objets Dictionnaire utiles en désérialisant les résultats de votre URL.
Je viens d'écrire une classe appelée JSON, qui rend la gestion JSON dans Swift aussi simple que l'objet JSON dans ES5.
Transformez votre objet Swift en JSON comme suit:
let obj:[String:AnyObject] = [
"array": [JSON.null, false, 0, "",[],[:]],
"object":[
"null": JSON.null,
"bool": true,
"int": 42,
"double": 3.141592653589793,
"string": "a α\t弾\n????",
"array": [],
"object": [:]
],
"url":"http://blog.livedoor.com/dankogai/"
]
let json = JSON(obj)
json.toString()
... ou de la ficelle ...
let json = JSON.parse("{\"array\":[...}")
... ou une URL.
let json = JSON.fromURL("http://api.dan.co.jp/jsonenv")
Tree Traversal
Il suffit de parcourir les éléments via un indice:
json["object"]["null"].asNull // NSNull()
// ...
json["object"]["string"].asString // "a α\t弾\n????"
json["array"][0].asNull // NSNull()
json["array"][1].asBool // false
// ...
Tout comme SwiftyJSON vous ne vous inquiétez pas si l'entrée en indice n'existe pas.
if let b = json["noexistent"][1234567890]["entry"].asBool {
// ....
} else {
let e = json["noexistent"][1234567890]["entry"].asError
println(e)
}
Si vous êtes fatigué des indices, ajoutez votre schéma comme suit:
//// schema by subclassing
class MyJSON : JSON {
init(_ obj:AnyObject){ super.init(obj) }
init(_ json:JSON) { super.init(json) }
var null :NSNull? { return self["null"].asNull }
var bool :Bool? { return self["bool"].asBool }
var int :Int? { return self["int"].asInt }
var double:Double? { return self["double"].asDouble }
var string:String? { return self["string"].asString }
}
Et vous allez:
let myjson = MyJSON(obj)
myjson.object.null
myjson.object.bool
myjson.object.int
myjson.object.double
myjson.object.string
// ...
J'espère que vous aimez.
Avec le nouveau xCode 7.3+, il est important d’ajouter votre domaine à la liste des exceptions ( Comment puis-je ajouter NSAppTransportSecurity à mon fichier info.plist? ), consultez cette publication pour obtenir des instructions, sinon vous obtiendrez une erreur de l'autorité de transport .
Voici un code pour effectuer les conversions entre JSON et NSData dans Swift 2.0
// Convert from NSData to json object
func nsdataToJSON(data: NSData) -> AnyObject? {
do {
return try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
} catch let myJSONError {
print(myJSONError)
}
return nil
}
// Convert from JSON to nsdata
func jsonToNSData(json: AnyObject) -> NSData?{
do {
return try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted)
} catch let myJSONError {
print(myJSONError)
}
return nil;
}
Dead-simple et facile à lire!
"mrap"
à partir de nicknames
en tant que chaîne à partir de cette réponse JSON{
"other": {
"nicknames": ["mrap", "Mikee"]
}
Cela prend vos données json NSData
telles quelles, pas besoin de prétraiter.
let parser = JSONParser(jsonData)
if let handle = parser.getString("other.nicknames[0]") {
// that's it!
}
Disclaimer: J'ai fait ça et j'espère que ça aidera tout le monde. N'hésitez pas à l'améliorer!
Étape 1. Installez Swifty Json https://github.com/SwiftyJSON/SwiftyJSON
Note: _ si vous le cherchez, vous risquez fort de ne pas savoir comment installer swifty. Suivez les instructions à https: //guides.cocoapods .org/using/getting-started.html # toc_3
Sudo gem installer des cocoapods
cd ~/Chemin/Vers/Dossier/Contenant/ShowTracker
Ensuite, entrez cette commande:
pod init
Cela créera un fichier podfile par défaut pour votre projet. Le fichier podfile vous permet de définir les dépendances sur lesquelles repose votre projet.
Tapez cette commande pour ouvrir Podfile en utilisant Xcode à des fins d'édition:
open -a Xcode Podfile
Ajouter le Swifty dans le podfile
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'SwiftyJSON', '~> X.X.X'
end
Étape 2. Vérifiez cet exemple
var mURL = NSURL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&units=metric")
if mURL == nil{
println("You are stupid")
return
}
var request = NSURLRequest(URL: mURL!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if data != nil {
var mJSON = JSON(data: data!)
if let current_conditions = mJSON["weather"][0]["description"].string{
println("Current conditions: " + current_conditions)
} else {
println("MORON!")
}
if let current_temperature = mJSON["main"]["temp"].double{
println("Temperature: "+ String(format:"%.f", current_temperature) + "°C"
} else {
println("MORON!")
}
}
})
Étape 3. Bénéfice
L'analyse de JSON dans Swift est un excellent travail pour la génération de code. J'ai créé un outil sur http://www.guideluxe.com/JsonToSwift pour le faire.
Vous fournissez un exemple d'objet JSON avec un nom de classe et l'outil génère une classe Swift correspondante, ainsi que toutes les classes subsidiaires Swift nécessaires, pour représenter la structure implicite de l'exemple JSON. Sont également incluses les méthodes de classe utilisées pour renseigner les objets Swift, y compris celle qui utilise la méthode NSJSONSerialization.JSONObjectWithData. Les mappages nécessaires des objets NSArray et NSDictionary sont fournis.
À partir du code généré, vous devez uniquement fournir un objet NSData contenant JSON correspondant à l'exemple fourni à l'outil.
Autre que Foundation, il n'y a pas de dépendances.
Mon travail a été inspiré par http://json2csharp.com/ , qui est très pratique pour les projets .NET.
Voici comment créer un objet NSData à partir d'un fichier JSON.
let fileUrl: NSURL = NSBundle.mainBundle().URLForResource("JsonFile", withExtension: "json")!
let jsonData: NSData = NSData(contentsOfURL: fileUrl)!
J'ai également écrit une petite bibliothèque spécialisée pour la mise en correspondance de la réponse JSON dans une structure d'objet. J'utilise en interne la bibliothèque Json-Swift de David Owens. Peut-être que c'est utile pour quelqu'un d'autre.
https://github.com/prine/ROJSONParser
Exemple Employees.json
{
"employees": [
{
"firstName": "John",
"lastName": "Doe",
"age": 26
},
{
"firstName": "Anna",
"lastName": "Smith",
"age": 30
},
{
"firstName": "Peter",
"lastName": "Jones",
"age": 45
}]
}
La prochaine étape consiste à créer votre modèle de données (EmplyoeeContainer and Employee).
Employee.Swift
class Employee : ROJSONObject {
required init() {
super.init();
}
required init(jsonData:AnyObject) {
super.init(jsonData: jsonData)
}
var firstname:String {
return Value<String>.get(self, key: "firstName")
}
var lastname:String {
return Value<String>.get(self, key: "lastName")
}
var age:Int {
return Value<Int>.get(self, key: "age")
}
}
EmployeeContainer.Swift
class EmployeeContainer : ROJSONObject {
required init() {
super.init();
}
required init(jsonData:AnyObject) {
super.init(jsonData: jsonData)
}
lazy var employees:[Employee] = {
return Value<[Employee]>.getArray(self, key: "employees") as [Employee]
}()
}
Ensuite, pour mapper les objets de la réponse JSON, il suffit de transmettre les données à la classe EmployeeContainer en tant que paramètre du constructeur. Il crée automatiquement votre modèle de données.
var baseWebservice:BaseWebservice = BaseWebservice();
var urlToJSON = "http://prine.ch/employees.json"
var callbackJSON = {(status:Int, employeeContainer:EmployeeContainer) -> () in
for employee in employeeContainer.employees {
println("Firstname: \(employee.firstname) Lastname: \(employee.lastname) age: \(employee.age)")
}
}
baseWebservice.get(urlToJSON, callback:callbackJSON)
La sortie de la console se présente alors comme suit:
Firstname: John Lastname: Doe age: 26
Firstname: Anna Lastname: Smith age: 30
Firstname: Peter Lastname: Jones age: 45
Swift 3
let parsedResult: [String: AnyObject]
do {
parsedResult = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:AnyObject]
} catch {
// Display an error or return or whatever
}
data - son type de données (Structure) (c'est-à-dire renvoyé par une réponse du serveur)
Utilisation de Framework ObjectMapper
if let path = Bundle(for: BPPView.self).path(forResource: jsonFileName, ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: NSData.ReadingOptions.mappedIfSafe)
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
self.levels = Mapper<Level>().mapArray(JSONArray: (json as! [[String : Any]]))!
print(levels.count)
} catch let error as NSError {
print(error.localizedDescription)
}
} else {
print("Invalid filename/path.")
}
Avant de préparer l’ensemble d’objectifs: Objets mappables à analyser
import UIKit
import ObjectMapper
class Level: Mappable {
var levelName = ""
var levelItems = [LevelItem]()
required init?(map: Map) {
}
// Mappable
func mapping(map: Map) {
levelName <- map["levelName"]
levelItems <- map["levelItems"]
}
}
import UIKit
import ObjectMapper
class LevelItem: Mappable {
var frontBackSide = BPPFrontBack.Undefined
var fullImageName = ""
var fullImageSelectedName = ""
var bodyParts = [BodyPart]()
required init?(map: Map) {
}
// Mappable
func mapping(map: Map) {
frontBackSide <- map["frontBackSide"]
fullImageName <- map["fullImageName"]
fullImageSelectedName <- map["fullImageSelectedName"]
bodyParts <- map["bodyParts"]
}}
L'ensemble du contrôleur de vue, qui affiche les données dans la vue Collection à l'aide de deux méthodes d'analyse json
@IBOutlet weak var imagecollectionview: UICollectionView!
lazy var data = NSMutableData()
var dictdata : NSMutableDictionary = NSMutableDictionary()
override func viewDidLoad() {
super.viewDidLoad()
startConnection()
startNewConnection()
// Do any additional setup after loading the view, typically from a nib.
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dictdata.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CustomcellCollectionViewCell", forIndexPath: indexPath) as! CustomcellCollectionViewCell
cell.name.text = dictdata.valueForKey("Data")?.valueForKey("location") as? String
let url = NSURL(string: (dictdata.valueForKey("Data")?.valueForKey("avatar_url") as? String)! )
LazyImage.showForImageView(cell.image, url:"URL
return cell
}
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let kWhateverHeightYouWant = 100
return CGSizeMake(self.view.bounds.size.width/2, CGFloat(kWhateverHeightYouWant))
}
func startNewConnection()
{
let url: URL = URL(string: "YOUR URL" as String)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "GET" //set the get or post according to your request
// request.cachePolicy = NSURLRequest.CachePolicy.ReloadIgnoringCacheData
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) {
( data, response, error) in
guard let _:NSData = data as NSData?, let _:URLResponse = response, error == nil else {
print("error")
return
}
let jsonString = NSString(data: data!, encoding:String.Encoding.utf8.rawValue) as! String
}
task.resume()
}
func startConnection(){
let urlPath: String = "your URL"
let url: NSURL = NSURL(string: urlPath)!
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
connection.start()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
self.data.appendData(data)
}
func buttonAction(sender: UIButton!){
startConnection()
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
do {
let JSON = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions(rawValue: 0))
guard let JSONDictionary :NSDictionary = JSON as? NSDictionary else {
print("Not a Dictionary")
// put in function
return
}
print("JSONDictionary! \(JSONDictionary)")
dictdata.setObject(JSONDictionary, forKey: "Data")
imagecollectionview.reloadData()
}
catch let JSONError as NSError {
print("\(JSONError)")
} }
Dans Swift 4+, il est fortement recommandé d’utiliser Codable
au lieu de JSONSerialization
.
Cette Codable
inclut deux protocoles: Decodable
et Encodable
. Ce protocole Decodable
vous permet de décoder Data
au format JSON en structure/classe personnalisée conforme à ce protocole.
Par exemple, imaginons que nous ayons cette simple Data
(tableau de deux objets)
let data = Data("""
[
{"name":"Steve","age":56},
{"name":"iPhone","age":11}
]
""".utf8)
puis suivre struct
et implémenter le protocole Decodable
struct Person: Decodable {
let name: String
let age: Int
}
vous pouvez maintenant décoder votre Data
dans votre tableau de Person
en utilisant JSONDecoder
où le premier paramètre correspond à un type conforme à Decodable
et à ce type si Data
doit être décodé
do {
let people = try JSONDecoder().decode([Person].self, from: data)
} catch { print(error) }
... notez que le décodage doit être marqué avec le mot clé try
car vous pouvez par exemple faire une erreur de nommage et ensuite votre modèle ne peut pas être décodé correctement ... vous devez donc l'insérer dans le bloc do-try-catch
Les cas que json dans json sont différents du nom de la propriété:
Si key est nommé avec snake_case, vous pouvez définir keyDecodingStrategy
du décodeur sur convertFromSnakeCase
, ce qui change la clé de property_name
en camelCase propertyName
.
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let people = try decoder.decode([Person].self, from: data)
Si vous avez besoin d'un nom unique, vous pouvez utiliser clés de codage à l'intérieur de struct/class où vous déclarez le nom de la clé
let data = Data("""
{ "userName":"Codable", "age": 1 }
""".utf8)
struct Person: Decodable {
let name: String
let age: Int
enum CodingKeys: String, CodingKey {
case name = "userName"
case age
}
}
Utiliser JSONDecoder().decode
Voir cette vidéo Analyse JSON avec Swift 4
struct Post: Codable {
let userId: Int
let id: Int
let title: String
let body: String
}
URLSession.shared.dataTask(with: URL(string: "https://jsonplaceholder.typicode.com/posts")!) { (data, response, error) in
guard let response = response as? HTTPURLResponse else {
print("HTTPURLResponse error")
return
}
guard 200 ... 299 ~= response.statusCode else {
print("Status Code error \(response.statusCode)")
return
}
guard let data = data else {
print("No Data")
return
}
let posts = try! JSONDecoder().decode([Post].self, from: data)
print(posts)
}.resume()
Swift 4
Créer un projet
Design StoryBoard avec un bouton et une UITableview
Créer une tableViewCell VC
Dans l'action des boutons Insérez les codes suivants
Mémoriser ce code pour extraire un tableau de données dans une API
import UIKit
class ViewController3: UIViewController,UITableViewDelegate,UITableViewDataSource {
@IBOutlet var tableView: UITableView!
var displayDatasssss = [displyDataClass]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return displayDatasssss.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell1") as! TableViewCell1
cell.label1.text = displayDatasssss[indexPath.row].email
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gettt(_ sender: Any) {
let url = "http://jsonplaceholder.typicode.com/users"
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request){(data, response,error)in
if (error != nil){
print("Error")
}
else{
do{
// Array of Data
let fetchData = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! NSArray
for eachData in fetchData {
let eachdataitem = eachData as! [String : Any]
let name = eachdataitem["name"]as! String
let username = eachdataitem["username"]as! String
let email = eachdataitem["email"]as! String
self.displayDatasssss.append(displyDataClass(name: name, username: username,email : email))
}
self.tableView.reloadData()
}
catch{
print("Error 2")
}
}
}
task.resume()
}
}
class displyDataClass {
var name : String
var username : String
var email : String
init(name : String,username : String,email :String) {
self.name = name
self.username = username
self.email = email
}
}
Ceci est pour la récupération de données de dictionnaire
import UIKit
class ViewController3: UIViewController,UITableViewDelegate,UITableViewDataSource {
@IBOutlet var tableView: UITableView!
var displayDatasssss = [displyDataClass]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return displayDatasssss.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell1") as! TableViewCell1
cell.label1.text = displayDatasssss[indexPath.row].email
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gettt(_ sender: Any) {
let url = "http://jsonplaceholder.typicode.com/users/1"
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request){(data, response,error)in
if (error != nil){
print("Error")
}
else{
do{
//Dictionary data Fetching
let fetchData = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String: AnyObject]
let name = fetchData["name"]as! String
let username = fetchData["username"]as! String
let email = fetchData["email"]as! String
self.displayDatasssss.append(displyDataClass(name: name, username: username,email : email))
self.tableView.reloadData()
}
catch{
print("Error 2")
}
}
}
task.resume()
}
}
class displyDataClass {
var name : String
var username : String
var email : String
init(name : String,username : String,email :String) {
self.name = name
self.username = username
self.email = email
}
}
Voici un exemple de terrain de jeu Swift:
import UIKit
let jsonString = "{\"name\": \"John Doe\", \"phone\":123456}"
let data = jsonString.data(using: .utf8)
var jsonObject: Any
do {
jsonObject = try JSONSerialization.jsonObject(with: data!) as Any
if let obj = jsonObject as? NSDictionary {
print(obj["name"])
}
} catch {
print("error")
}
Swift2 iOs9
let miadata = NSData(contentsOfURL: NSURL(string: "https://myWeb....php")!)
do{
let MyData = try NSJSONSerialization.JSONObjectWithData(miadata!, options: NSJSONReadingOptions.MutableContainers) as? NSArray
print(".........\(MyData)")
}
catch let error as NSError{
// error.description
print(error.description)
}
Cet analyseur utilise des génériques pour convertir les types JSON en Swift, ce qui réduit le code à taper.
https://github.com/evgenyneu/JsonSwiftson
struct Person {
let name: String?
let age: Int?
}
let mapper = JsonSwiftson(json: "{ \"name\": \"Peter\", \"age\": 41 }")
let person: Person? = Person(
name: mapper["name"].map(),
age: mapper["age"].map()
)