Mam plik JSON, chcę przeanalizować i użyć listy obiektów w widoku tabeli. Czy każdy może udostępnić kod, aby przeanalizować plik JSON w szybkim tempie.
Mam plik JSON, chcę przeanalizować i użyć listy obiektów w widoku tabeli. Czy każdy może udostępnić kod, aby przeanalizować plik JSON w szybkim tempie.
Odpowiedzi:
Nie może być prostsze:
import Foundation
let jsonData: Data = /* get your json data */
let jsonDict = try JSONSerialization.jsonObject(with: jsonData) as? NSDictionary
Biorąc to pod uwagę, zdecydowanie zalecam używanie Codable API wprowadzonych w Swift 4.
let jsonData = NSData.dataWithContentsOfFile(filepath, options: .DataReadingMappedIfSafe, error: nil)
NSData(contentsOfFile: path). Zobacz developer.apple.com/library/ios/documentation/Cocoa/Reference/… :
Wykonanie żądania API
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
Przygotowanie do odpowiedzi
Zadeklaruj tablicę jak poniżej
var data: NSMutableData = NSMutableData()
Otrzymanie odpowiedzi
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()
}
}
Po NSURLConnectionotrzymaniu odpowiedzi możemy spodziewać didReceiveResponsesię wywołania metody w naszym imieniu. W tym momencie po prostu resetujemy nasze dane, mówiąc self.data = NSMutableData(), tworząc nowy pusty obiekt danych.
Po nawiązaniu połączenia zaczniemy odbierać dane w metodzie didReceiveData. Argument danych, który jest tutaj przekazywany, jest źródłem wszystkich naszych soczystych informacji. Musimy trzymać się każdego przychodzącego fragmentu, więc dołączamy go do obiektu self.data, który wyczyściliśmy wcześniej.
Na koniec, gdy połączenie jest zakończone i wszystkie dane zostały odebrane, connectionDidFinishLoadingzostaje wywołany i jesteśmy gotowi do użycia danych w naszej aplikacji. Brawo!
Ta connectionDidFinishLoadingmetoda używa NSJSONSerializationklasy do konwersji naszych surowych danych na przydatne Dictionaryobiekty poprzez deserializację wyników z adresu URL.
Właśnie napisałem klasę o nazwie JSON, która sprawia, że obsługa JSON w Swift jest tak łatwa jak obiekt JSON w ES5.
Zmień swój szybki obiekt na JSON w ten sposób:
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()
... lub sznurek ...
let json = JSON.parse("{\"array\":[...}")
... lub URL.
let json = JSON.fromURL("http://api.dan.co.jp/jsonenv")
Tree Traversal
Po prostu przejdź przez elementy za pomocą indeksu dolnego:
json["object"]["null"].asNull // NSNull()
// ...
json["object"]["string"].asString // "a α\t弾\n𪚲"
json["array"][0].asNull // NSNull()
json["array"][1].asBool // false
// ...
Podobnie jak SwiftyJSON , nie martwisz się, jeśli wpis z indeksem nie istnieje.
if let b = json["noexistent"][1234567890]["entry"].asBool {
// ....
} else {
let e = json["noexistent"][1234567890]["entry"].asError
println(e)
}
Jeśli masz dość indeksów dolnych, dodaj swój schemat w następujący sposób:
//// 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 }
}
I idziesz:
let myjson = MyJSON(obj)
myjson.object.null
myjson.object.bool
myjson.object.int
myjson.object.double
myjson.object.string
// ...
Mam nadzieję że ci się spodoba.
Wraz z nowym xCode 7.3+ ważne jest, aby dodać swoją domenę do listy wyjątków ( Jak mogę dodać NSAppTransportSecurity do mojego pliku info.plist? ), Zapoznaj się z tym wpisem , aby uzyskać instrukcje, w przeciwnym razie otrzymasz błąd organu transportu.
Oto kod umożliwiający konwersję między JSON i NSData w 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;
}
W Swift 4+ zdecydowanie zaleca się używanie Codablezamiast JSONSerialization.
Obejmuje Codableto dwa protokoły: Decodablei Encodable. Ten Decodableprotokół umożliwia dekodowanie Dataw formacie JSON do niestandardowej struktury / klasy zgodnej z tym protokołem.
Na przykład wyobraź sobie sytuację, w której mamy to proste Data(tablica dwóch obiektów)
let data = Data("""
[
{"name":"Steve","age":56},
{"name":"iPhone","age":11}
]
""".utf8)
następnie wykonaj następujące czynności structi zastosuj protokółDecodable
struct Person: Decodable {
let name: String
let age: Int
}
teraz możesz zdekodować swoją Datatablicę Personużywając JSONDecodergdzie pierwszy parametr jest zgodny z typem Decodablei do tego typu powinien Databyć dekodowany
do {
let people = try JSONDecoder().decode([Person].self, from: data)
} catch { print(error) }
... zwróć uwagę, że dekodowanie musi być oznaczone trysłowem kluczowym, ponieważ możesz na przykład popełnić błąd w nazewnictwie i wtedy twój model nie może zostać poprawnie zdekodowany ... więc powinieneś umieścić go w bloku do-try-catch
Przypadki, w których klucz w json różni się od nazwy właściwości:
Jeśli klucz jest nazwany przy użyciu snake_case, możesz ustawić dekoder, keyDecodingStrategydo convertFromSnakeCasektórego zmienia klucz z property_namena camelCasepropertyName
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let people = try decoder.decode([Person].self, from: data)
Jeśli potrzebujesz unikalnej nazwy, możesz użyć kluczy kodowania wewnątrz struktury / klasy, w której deklarujesz nazwę klucza
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
}
}
Napisałem również małą bibliotekę, która specjalizuje się w mapowaniu odpowiedzi json na strukturę obiektu. Używam wewnętrznie biblioteki json-swift od Davida Owensa. Może przyda się komuś innemu.
https://github.com/prine/ROJSONParser
Przykład Employees.json
{
"employees": [
{
"firstName": "John",
"lastName": "Doe",
"age": 26
},
{
"firstName": "Anna",
"lastName": "Smith",
"age": 30
},
{
"firstName": "Peter",
"lastName": "Jones",
"age": 45
}]
}
W kolejnym kroku musisz stworzyć swój model danych (EmplyoeeContainer i 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]
}()
}
Następnie, aby faktycznie zmapować obiekty z odpowiedzi JSON, wystarczy przekazać dane do klasy EmployeeContainer jako parametr w konstruktorze. Automatycznie tworzy model danych.
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)
Wynik konsoli wygląda wtedy następująco:
Firstname: John Lastname: Doe age: 26
Firstname: Anna Lastname: Smith age: 30
Firstname: Peter Lastname: Jones age: 45
Śmiertelnie proste i łatwe do odczytania!
"mrap"z nicknamesjako String z tej odpowiedzi JSON{
"other": {
"nicknames": ["mrap", "Mikee"]
}
Zajmuje dane json NSDatatakie, jakie są, nie ma potrzeby wstępnego przetwarzania.
let parser = JSONParser(jsonData)
if let handle = parser.getString("other.nicknames[0]") {
// that's it!
}
Zastrzeżenie: zrobiłem to i mam nadzieję, że pomoże to wszystkim. Zapraszam do ulepszania go!
Parsowanie JSON w Swift to doskonała praca do generowania kodu. Stworzyłem narzędzie pod adresem http://www.guideluxe.com/JsonToSwift, aby to zrobić.
Dostarczasz przykładowy obiekt JSON z nazwą klasy, a narzędzie wygeneruje odpowiednią klasę Swift, a także wszelkie potrzebne dodatkowe klasy Swift, aby przedstawić strukturę implikowaną przez przykładowy JSON. Dołączone są również metody klas używane do wypełniania obiektów Swift, w tym metoda wykorzystująca metodę NSJSONSerialization.JSONObjectWithData. Zapewnione są niezbędne mapowania z obiektów NSArray i NSDictionary.
Z wygenerowanego kodu wystarczy dostarczyć obiekt NSData zawierający JSON, który pasuje do przykładu dostarczonego do narzędzia.
Poza Foundation nie ma żadnych zależności.
Moja praca została zainspirowana http://json2csharp.com/ , co jest bardzo przydatne w projektach .NET.
Oto jak utworzyć obiekt NSData z pliku JSON.
let fileUrl: NSURL = NSBundle.mainBundle().URLForResource("JsonFile", withExtension: "json")!
let jsonData: NSData = NSData(contentsOfURL: fileUrl)!
Uwaga: jeśli tego szukasz, istnieje również duża szansa, że nie wiesz, jak zainstalować swifty. Postępuj zgodnie z instrukcjami tutaj .
sudo gem install cocoapods
cd ~/Path/To/Folder/Containing/ShowTracker
Następnie wprowadź to polecenie:
pod init
Spowoduje to utworzenie domyślnego Podfileprojektu. To miejsce, w Podfilektórym definiujesz zależności, na których opiera się Twój projekt.
Wpisz to polecenie, aby otworzyć Podfileza pomocą Xcodedo edycji:
open -a Xcode Podfile
Dodaj Swiftydo pliku 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!")
}
}
})
Cały kontroler widoku, który wyświetla dane w widoku kolekcji przy użyciu dwóch metod json parsig
@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)")
} }
Korzystanie z platformy 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.")
}
Wcześniej należy przygotować zestaw odpowiednich: Mapowalnych obiektów do parsowania
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"]
}}
Szybki 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
}
dane - to typ danych (struktura) (tj. zwracane przez odpowiedź serwera)
Ten parser używa typów ogólnych do rzutowania JSON na typy Swift, co ogranicza kod, który musisz wpisać.
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()
)
Poniżej znajduje się przykład 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")
}
Szybki 4
Utwórz projekt
Zaprojektuj StoryBoard za pomocą przycisku i widoku UITableview
Utwórz TableViewCell VC
W akcji przycisku Wstaw następujące kody
Zapamiętaj ten kod, aby pobrać tablicę danych w interfejsie 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
}
}
Dotyczy to pobierania danych ze słownika
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
}
}
Zrobić użytek z JSONDecoder().decode
Zobacz ten film o parsowaniu JSON w 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)
}