Ho un file JSON, desidero analizzare e utilizzare l'elenco di oggetti nella visualizzazione tabella. Chiunque può condividere il codice per analizzare il file JSON in modo rapido.
Ho un file JSON, desidero analizzare e utilizzare l'elenco di oggetti nella visualizzazione tabella. Chiunque può condividere il codice per analizzare il file JSON in modo rapido.
Risposte:
Non potrebbe essere più semplice:
import Foundation
let jsonData: Data = /* get your json data */
let jsonDict = try JSONSerialization.jsonObject(with: jsonData) as? NSDictionary
Detto questo, consiglio vivamente di utilizzare le API codificabili introdotte in Swift 4.
let jsonData = NSData.dataWithContentsOfFile(filepath, options: .DataReadingMappedIfSafe, error: nil)
NSData(contentsOfFile: path)
. Vedi developer.apple.com/library/ios/documentation/Cocoa/Reference/… :
Effettuare la richiesta API
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
Prepararsi per la risposta
Dichiara un array come di seguito
var data: NSMutableData = NSMutableData()
Ricezione della risposta
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()
}
}
Quando NSURLConnection
riceve una risposta, possiamo aspettarci che il didReceiveResponse
metodo venga chiamato per nostro conto. A questo punto ripristiniamo semplicemente i nostri dati dicendo self.data = NSMutableData()
, creando un nuovo oggetto dati vuoto.
Dopo aver stabilito una connessione, inizieremo a ricevere i dati nel metodo didReceiveData
. L'argomento dati che viene passato qui è da dove provengono tutte le nostre succose informazioni. Dobbiamo mantenere ogni pezzo che arriva, quindi lo aggiungiamo all'oggetto self.data che abbiamo eliminato in precedenza.
Infine, quando la connessione è terminata e tutti i dati sono stati ricevuti, connectionDidFinishLoading
viene chiamato e siamo pronti per utilizzare i dati nella nostra app. Evviva!
Il connectionDidFinishLoading
metodo qui utilizza la NSJSONSerialization
classe per convertire i nostri dati grezzi in Dictionary
oggetti utili deserializzando i risultati dal tuo Url.
Ho appena scritto una classe chiamata JSON, che rende la gestione di JSON in Swift facile come un oggetto JSON in ES5.
Trasforma il tuo oggetto rapido in JSON in questo modo:
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()
... o stringa ...
let json = JSON.parse("{\"array\":[...}")
... o URL.
let json = JSON.fromURL("http://api.dan.co.jp/jsonenv")
Tree Traversal
Basta attraversare gli elementi tramite pedice:
json["object"]["null"].asNull // NSNull()
// ...
json["object"]["string"].asString // "a α\t弾\n𪚲"
json["array"][0].asNull // NSNull()
json["array"][1].asBool // false
// ...
Proprio come SwiftyJSON non ti preoccupi se la voce sottoscritta non esiste.
if let b = json["noexistent"][1234567890]["entry"].asBool {
// ....
} else {
let e = json["noexistent"][1234567890]["entry"].asError
println(e)
}
Se sei stanco dei pedici, aggiungi il tuo schema in questo modo:
//// 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 }
}
E tu vai:
let myjson = MyJSON(obj)
myjson.object.null
myjson.object.bool
myjson.object.int
myjson.object.double
myjson.object.string
// ...
Spero ti piaccia.
Con il nuovo xCode 7.3+ è importante aggiungere il tuo dominio all'elenco delle eccezioni ( come posso aggiungere NSAppTransportSecurity al mio file info.plist? ), Fai riferimento a questo messaggio per le istruzioni, altrimenti riceverai un errore di autorità di trasporto.
Ecco un codice per effettuare le conversioni tra JSON e NSData in 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;
}
In Swift 4+ si consiglia vivamente di utilizzare al Codable
posto di JSONSerialization
.
Ciò Codable
include due protocolli: Decodable
e Encodable
. Questo Decodable
protocollo consente di decodificare Data
in formato JSON in una struttura / classe personalizzata conforme a questo protocollo.
Ad esempio, immagina una situazione in cui abbiamo questo semplice Data
(array di due oggetti)
let data = Data("""
[
{"name":"Steve","age":56},
{"name":"iPhone","age":11}
]
""".utf8)
quindi seguire struct
e implementare il protocolloDecodable
struct Person: Decodable {
let name: String
let age: Int
}
ora puoi decodificare il tuo Data
nel tuo array di Person
utilizzo JSONDecoder
dove il primo parametro è il tipo conforme Decodable
e a questo tipo dovrebbe Data
essere decodificato
do {
let people = try JSONDecoder().decode([Person].self, from: data)
} catch { print(error) }
... nota che la decodifica deve essere contrassegnata con una try
parola chiave poiché potresti ad esempio fare qualche errore con la denominazione e quindi il tuo modello non può essere decodificato correttamente ... quindi dovresti inserirlo nel blocco do-try-catch
Casi in cui la chiave in json è diversa dal nome della proprietà:
Se la chiave è in named utilizzando snake_case, puoi impostare il decoder keyDecodingStrategy
su convertFromSnakeCase
cui cambia la chiave da property_name
a camelCasepropertyName
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let people = try decoder.decode([Person].self, from: data)
Se hai bisogno di un nome univoco puoi usare le chiavi di codifica all'interno della struttura / classe dove dichiari il nome della chiave
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
}
}
Ho anche scritto una piccola libreria specializzata per la mappatura della risposta json in una struttura di oggetti. Utilizzo internamente la libreria json-swift di David Owens. Forse è utile per qualcun altro.
https://github.com/prine/ROJSONParser
Esempio Employees.json
{
"employees": [
{
"firstName": "John",
"lastName": "Doe",
"age": 26
},
{
"firstName": "Anna",
"lastName": "Smith",
"age": 30
},
{
"firstName": "Peter",
"lastName": "Jones",
"age": 45
}]
}
Come passaggio successivo devi creare il tuo modello di dati (EmplyoeeContainer e 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]
}()
}
Quindi, per mappare effettivamente gli oggetti dalla risposta JSON, devi solo passare i dati nella classe EmployeeContainer come parametro nel costruttore. Crea automaticamente il tuo modello di dati.
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)
L'output della console sarà quindi simile al seguente:
Firstname: John Lastname: Doe age: 26
Firstname: Anna Lastname: Smith age: 30
Firstname: Peter Lastname: Jones age: 45
Semplice e facile da leggere!
"mrap"
da nicknames
come stringa da questa risposta JSON{
"other": {
"nicknames": ["mrap", "Mikee"]
}
Prende i tuoi dati JSON così NSData
come sono, non è necessario preelaborarli.
let parser = JSONParser(jsonData)
if let handle = parser.getString("other.nicknames[0]") {
// that's it!
}
Disclaimer: l'ho fatto e spero che aiuti tutti. Sentiti libero di migliorarlo!
L'analisi di JSON in Swift è un lavoro eccellente per la generazione di codice. Ho creato uno strumento a http://www.guideluxe.com/JsonToSwift di fare proprio questo.
Fornisci un oggetto JSON di esempio con un nome di classe e lo strumento genererà una classe Swift corrispondente, nonché tutte le classi Swift sussidiarie necessarie, per rappresentare la struttura implicita dal JSON di esempio. Sono inclusi anche i metodi di classe utilizzati per popolare gli oggetti Swift, incluso uno che utilizza il metodo NSJSONSerialization.JSONObjectWithData. Vengono forniti i mapping necessari dagli oggetti NSArray e NSDictionary.
Dal codice generato, devi solo fornire un oggetto NSData contenente JSON che corrisponda all'esempio fornito allo strumento.
Oltre a Foundation, non ci sono dipendenze.
Il mio lavoro è stato ispirato da http://json2csharp.com/ , molto utile per i progetti .NET.
Ecco come creare un oggetto NSData da un file JSON.
let fileUrl: NSURL = NSBundle.mainBundle().URLForResource("JsonFile", withExtension: "json")!
let jsonData: NSData = NSData(contentsOfURL: fileUrl)!
Nota: se stai cercando questo, c'è anche un'alta probabilità che tu non sappia come installare swifty
. Segui le istruzioni qui .
sudo gem install cocoapods
cd ~/Path/To/Folder/Containing/ShowTracker
Quindi inserisci questo comando:
pod init
Questo creerà un valore predefinito Podfile
per il tuo progetto. L' Podfile
è possibile definire le dipendenze del progetto si basa su.
Digita questo comando per aprire Podfile
utilizzando Xcode
per la modifica:
open -a Xcode Podfile
Aggiungi il file Swifty
nel podfile
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'SwiftyJSON', '~> X.X.X'
end
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!")
}
}
})
L'intero viewcontroller che mostra i dati nella vista della raccolta utilizzando due metodi di analisi 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)")
} }
Utilizzo del 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.")
}
Prima di preparare la serie di oggetti appropriati: mappabili da analizzare
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"]
}}
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
}
dati - è il tipo di dati (struttura) (cioè restituito da una risposta del server)
Questo parser utilizza generics per trasmettere JSON ai tipi Swift, riducendo il codice che devi digitare.
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()
)
Di seguito è riportato un esempio di Swift Playground:
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")
}
Swift 4
Crea un progetto
Progetta StoryBoard con un pulsante e un UITableview
Crea TableViewCell VC
Nell'azione del pulsante, inserire i seguenti codici
Ricorda questo codice per recuperare array di dati in un'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
}
}
Questo è per il recupero dei dati del dizionario
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
}
}
Utilizzare JSONDecoder().decode
Guarda questo video Analisi JSON con 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 2 iOS 9
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)
}