Szukałem dni, aby przekonwertować dość prosty ciąg JSON na typ obiektu w Swift, ale bezskutecznie.
Oto kod połączenia z usługą internetową:
func GetAllBusiness() {
Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
println(string)
}
}
Mam szybką strukturę Business.swift:
struct Business {
var Id : Int = 0
var Name = ""
var Latitude = ""
var Longitude = ""
var Address = ""
}
Oto moja wdrożona usługa testowa:
[
{
"Id": 1,
"Name": "A",
"Latitude": "-35.243256",
"Longitude": "149.110701",
"Address": null
},
{
"Id": 2,
"Name": "B",
"Latitude": "-35.240592",
"Longitude": "149.104843",
"Address": null
}
...
]
Byłoby wspaniale, gdyby ktoś mnie przez to przeprowadził.
Dzięki.
AnyObject
pomocą klucza, po prostu upewnij się, przed obniżeniem do String, że tak nie jestnil
. Z tego powodu możesz incapsualte używając!
lub w moim przypadku?
z holdplace??
var b:Business = Business()
poza pętlą boczną, może to pokazać te same dane w każdym elemencie listy.dla szybkiego 3/4
extension String { func toJSON() -> Any? { guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) } }
Przykładowe zastosowanie:
let dict = myString.toJSON() as? [String:AnyObject] // can be any type here
źródło
do-catch
,try?
można tu użyć, co da ten sam wynik, co zwrócenie zera wcatch
.extension String { func toJSON() -> Any? { guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) } }
Jako proste rozszerzenie String powinno wystarczyć:
extension String { var parseJSONString: AnyObject? { let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails return NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) } else { // Lossless conversion of the string was not possible return nil } } }
Następnie:
var jsonString = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" let json: AnyObject? = jsonString.parseJSONString println("Parsed JSON: \(json!)") println("json[3]: \(json![3])") /* Output: Parsed JSON: ( { id = 72; name = "Batata Cremosa"; }, { id = 183; name = "Caldeirada de Peixes"; }, { id = 76; name = "Batata com Cebola e Ervas"; }, { id = 56; name = "Arroz de forma"; } ) json[3]: { id = 56; name = "Arroz de forma"; } */
źródło
Swift 4 analizuje JSON znacznie bardziej elegancko. Po prostu zastosuj kodowalny protokół dla swojej struktury, zgodnie z tym uproszczonym przykładem:
struct Business: Codable { let id: Int let name: String }
Aby przeanalizować tablicę JSON, należy poinformować dekoder, jakie są obiekty tablicy danych
let parsedData = decoder.decode([Business].self, from: data)
Oto pełny przykład roboczy:
import Foundation struct Business: Codable { let id: Int let name: String } // Generating the example JSON data: let originalObjects = [Business(id: 0, name: "A"), Business(id: 1, name: "B")] let encoder = JSONEncoder() let data = try! encoder.encode(originalObjects) // Parsing the data: let decoder = JSONDecoder() let parsedData = try! decoder.decode([Business].self, from: data)
Więcej informacji znajdziesz w tym doskonałym przewodniku .
źródło
Dla Swift 4
Użyłem logiki @ Passkit , ale musiałem zaktualizować zgodnie ze Swift 4
Krok 1 Utworzono rozszerzenie dla klasy String
import UIKit extension String { var parseJSONString: AnyObject? { let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails do { let message = try JSONSerialization.jsonObject(with: jsonData, options:.mutableContainers) if let jsonResult = message as? NSMutableArray { print(jsonResult) return jsonResult //Will return the json array output } else { return nil } } catch let error as NSError { print("An error occurred: \(error)") return nil } } else { // Lossless conversion of the string was not possible return nil } } }
Krok 2 Oto jak użyłem w moim kontrolerze widoku
var jsonString = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" //Convert jsonString to jsonArray let json: AnyObject? = jsonString.parseJSONString print("Parsed JSON: \(json!)") print("json[2]: \(json![2])")
Wszystkie zasługi należą do pierwotnego użytkownika, właśnie zaktualizowałem do najnowszej szybkiej wersji
źródło
Napisałem bibliotekę, dzięki której praca z danymi json i deserializacja w Swift to pestka. Możesz go pobrać tutaj: https://github.com/isair/JSONHelper
Edycja: zaktualizowałem moją bibliotekę, możesz to teraz zrobić za pomocą tego:
class Business: Deserializable { var id: Int? var name = "N/A" // This one has a default value. required init(data: [String: AnyObject]) { id <-- data["id"] name <-- data["name"] } } var businesses: [Business]() Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in businesses <-- string }
Stara odpowiedź:
Po pierwsze, zamiast używać .responseString, użyj .response, aby uzyskać obiekt odpowiedzi. Następnie zmień kod na:
func getAllBusinesses() { Alamofire.request(.GET, "http://MyWebService/").response { (request, response, data, error) in var businesses: [Business]? businesses <-- data if businesses == nil { // Data was not structured as expected and deserialization failed, do something. } else { // Do something with your businesses array. } } }
Musisz stworzyć taką klasę biznesową:
class Business: Deserializable { var id: Int? var name = "N/A" // This one has a default value. required init(data: [String: AnyObject]) { id <-- data["id"] name <-- data["name"] } }
Pełną dokumentację można znaleźć w moim repozytorium GitHub. Baw się dobrze!
źródło
Dla Swift 4 napisałem to rozszerzenie przy użyciu protokołu Codable :
struct Business: Codable { var id: Int var name: String } extension String { func parse<D>(to type: D.Type) -> D? where D: Decodable { let data: Data = self.data(using: .utf8)! let decoder = JSONDecoder() do { let _object = try decoder.decode(type, from: data) return _object } catch { return nil } } } var jsonString = "[\n" + "{\n" + "\"id\":72,\n" + "\"name\":\"Batata Cremosa\",\n" + "},\n" + "{\n" + "\"id\":183,\n" + "\"name\":\"Caldeirada de Peixes\",\n" + "},\n" + "{\n" + "\"id\":76,\n" + "\"name\":\"Batata com Cebola e Ervas\",\n" + "},\n" + "{\n" + "\"id\":56,\n" + "\"name\":\"Arroz de forma\",\n" + "}]" let businesses = jsonString.parse(to: [Business].self)
źródło
Do
iOS 10
&Swift 3
, używając Alamofire & Gloss :Alamofire.request("http://localhost:8080/category/en").responseJSON { response in if let data = response.data { if let categories = [Category].from(data: response.data) { self.categories = categories self.categoryCollectionView.reloadData() } else { print("Casting error") } } else { print("Data is null") } }
a tutaj jest klasa Category
import Gloss struct Category: Decodable { let categoryId: Int? let name: String? let image: String? init?(json: JSON) { self.categoryId = "categoryId" <~~ json self.name = "name" <~~ json self.image = "image" <~~ json } }
IMO, to zdecydowanie najbardziej eleganckie rozwiązanie.
źródło
let jsonString = "{\"id\":123,\"Name\":\"Munish\"}"
Konwertuj ciąg na NSData
var data: NSData =jsonString.dataUsingEncoding(NSUTF8StringEncoding)! var error: NSError?
Konwertuj NSData na AnyObject
var jsonObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) println("Error: \\(error)") let id = (jsonObject as! NSDictionary)["id"] as! Int let name = (jsonObject as! NSDictionary)["name"] as! String println("Id: \\(id)") println("Name: \\(name)")
źródło
Podoba mi się odpowiedź RDC, ale po co ograniczać zwracany kod JSON, aby mieć tylko tablice na najwyższym poziomie? Musiałem zezwolić na słownik na najwyższym poziomie, więc zmodyfikowałem go w ten sposób:
extension String { var parseJSONString: AnyObject? { let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) if let jsonData = data { // Will return an object or nil if JSON decoding fails do { let message = try NSJSONSerialization.JSONObjectWithData(jsonData, options:.MutableContainers) if let jsonResult = message as? NSMutableArray { return jsonResult //Will return the json array output } else if let jsonResult = message as? NSMutableDictionary { return jsonResult //Will return the json dictionary output } else { return nil } } catch let error as NSError { print("An error occurred: \(error)") return nil } } else { // Lossless conversion of the string was not possible return nil } }
źródło
SWIFT4 - Łatwy i elegancki sposób dekodowania ciągów JSON do Struct.
Pierwszy krok - zakoduj łańcuch do danych z kodowaniem .utf8.
Następnie dekoduj swoje dane do YourDataStruct.
struct YourDataStruct: Codable { let type, id: String init(_ json: String, using encoding: String.Encoding = .utf8) throws { guard let data = json.data(using: encoding) else { throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil) } try self.init(data: data) } init(data: Data) throws { self = try JSONDecoder().decode(YourDataStruct.self, from: data) } } do { let successResponse = try WSDeleteDialogsResponse(response) } } catch {}
źródło
Możesz użyć swift.quicktype.io do konwersji
JSON
na albostruct
lubclass
. Nawet ty możesz wspomnieć o wersji kodu swift to genrate.Przykład JSON:
{ "message": "Hello, World!" }
Wygenerowany kod:
import Foundation typealias Sample = OtherSample struct OtherSample: Codable { let message: String } // Serialization extensions extension OtherSample { static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherSample? { guard let data = json.data(using: encoding) else { return nil } return OtherSample.from(data: data) } static func from(data: Data) -> OtherSample? { let decoder = JSONDecoder() return try? decoder.decode(OtherSample.self, from: data) } var jsonData: Data? { let encoder = JSONEncoder() return try? encoder.encode(self) } var jsonString: String? { guard let data = self.jsonData else { return nil } return String(data: data, encoding: .utf8) } } extension OtherSample { enum CodingKeys: String, CodingKey { case message } }
źródło
Korzystając z biblioteki SwiftyJSON , możesz to zrobić
if let path : String = Bundle.main.path(forResource: "tiles", ofType: "json") { if let data = NSData(contentsOfFile: path) { let optData = try? JSON(data: data as Data) guard let json = optData else { return } for (_, object) in json { let name = object["name"].stringValue print(name) } } }
źródło
Oto próbka, dzięki której wszystko będzie prostsze i łatwiejsze. Moje dane String w mojej bazie danych to plik JSON, który wygląda następująco:
[{"stype":"noun","sdsc":"careless disregard for consequences","swds":"disregard, freedom, impulse, licentiousness, recklessness, spontaneity, thoughtlessness, uninhibitedness, unrestraint, wantonness, wildness","anwds":"restraint, self-restraint"},{"stype":"verb","sdsc":"leave behind, relinquish","swds":"abdicate, back out, bail out, bow out, chicken out, cop out, cut loose, desert, discard, discontinue, ditch, drop, drop out, duck, dump, dust, flake out, fly the coop, give up the ship, kiss goodbye, leave, leg it, let go, opt out, pull out, quit, run out on, screw, ship out, stop, storm out, surrender, take a powder, take a walk, throw over, vacate, walk out on, wash hands of, withdraw, yield","anwds":"adopt, advance, allow, assert, begin, cherish, come, continue, defend, favor, go, hold, keep, maintain, persevere, pursue, remain, retain, start, stay, support, uphold"},{"stype":"verb","sdsc":"leave in troubled state","swds":"back out, desert, disown, forsake, jilt, leave, leave behind, quit, reject, renounce, throw over, walk out on","anwds":"adopt, allow, approve, assert, cherish, come, continue, defend, favor, keep, pursue, retain, stay, support, uphold"}]
Aby załadować te dane ciągów JSON, wykonaj następujące proste kroki. Najpierw utwórz klasę dla mojego obiektu MoreData w następujący sposób:
class MoreData { public private(set) var stype : String public private(set) var sdsc : String public private(set) var swds : String public private(set) var anwds : String init( stype : String, sdsc : String, swds : String, anwds : String) { self.stype = stype self.sdsc = sdsc self.swds = swds self.anwds = anwds }}
Po drugie, utwórz moje rozszerzenie String dla mojego ciągu JSON w następujący sposób:
extension String { func toJSON() -> Any? { guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) }}
Po trzecie, utwórz klasę My Srevices, aby obsłużyć moje dane ciągów w następujący sposób:
class Services { static let instance: Services = Services() func loadMoreDataByString(byString: String) -> [MoreData]{ var myVariable = [MoreData]() guard let ListOf = byString.toJSON() as? [[String: AnyObject]] else { return [] } for object in ListOf { let stype = object["stype"] as? String ?? "" let sdsc = object["sdsc"] as? String ?? "" let swds = object["swds"] as? String ?? "" let anwds = object["anwds"] as? String ?? "" let myMoreData = MoreData(stype : stype, sdsc : sdsc, swds : swds, anwds : anwds) myVariable.append(myMoreData) } return myVariable }}
Na koniec wywołaj tę funkcję z kontrolera widoku, aby załadować dane w widoku tabeli w następujący sposób:
func handlingJsonStringData(){ moreData.removeAll(keepingCapacity: false) moreData = Services.instance.loadMoreDataByString(byString: jsonString) print(self.moreData.count) tableView.reloadData() }
źródło
Może ktoś pomoże. Podobny przykład.
To jest nasza
Codable
klasa do wiązania danych. Możesz łatwo utworzyć tę klasę za pomocą SwiftyJsonAcceleratorclass ModelPushNotificationFilesFile: Codable { enum CodingKeys: String, CodingKey { case url case id case fileExtension = "file_extension" case name } var url: String? var id: Int? var fileExtension: String? var name: String? init (url: String?, id: Int?, fileExtension: String?, name: String?) { self.url = url self.id = id self.fileExtension = fileExtension self.name = name } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) url = try container.decodeIfPresent(String.self, forKey: .url) id = try container.decodeIfPresent(Int.self, forKey: .id) fileExtension = try container.decodeIfPresent(String.self, forKey: .fileExtension) name = try container.decodeIfPresent(String.self, forKey: .name) } }
To jest Json String
let jsonString = "[{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/tulips.png\"}, {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/arctichare.png\"}, {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/serrano.png\"}, {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/peppers.png\"}, {\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/pool.png\"}]"
Tutaj konwertujemy na szybki obiekt.
let jsonData = Data(jsonString.utf8) let decoder = JSONDecoder() do { let fileArray = try decoder.decode([ModelPushNotificationFilesFile].self, from: jsonData) print(fileArray) print(fileArray[0].url) } catch { print(error.localizedDescription) }
źródło
Użyj swiftyJson swiftyJson
platform :ios, '8.0' use_frameworks! target 'MyApp' do pod 'SwiftyJSON', '~> 4.0' end
Stosowanie
import SwiftyJSON let json = JSON(jsonObject) let id = json["Id"].intValue let name = json["Name"].stringValue let lat = json["Latitude"].stringValue let long = json["Longitude"].stringValue let address = json["Address"].stringValue print(id) print(name) print(lat) print(long) print(address)
źródło