Я искал несколько дней, чтобы преобразовать довольно простую строку JSON в тип объекта в Swift, но безрезультатно.
Вот код для вызова веб-службы:
func GetAllBusiness() {
Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
println(string)
}
}
У меня есть быстрая структура Business.swift:
struct Business {
var Id : Int = 0
var Name = ""
var Latitude = ""
var Longitude = ""
var Address = ""
}
Вот моя тестовая служба:
[
{
"Id": 1,
"Name": "A",
"Latitude": "-35.243256",
"Longitude": "149.110701",
"Address": null
},
{
"Id": 2,
"Name": "B",
"Latitude": "-35.240592",
"Longitude": "149.104843",
"Address": null
}
...
]
Было бы здорово, если бы кто-нибудь помог мне в этом.
Благодарю.
AnyObject
ключ, просто убедитесь, прежде чем понижать до String, что это не такnil
. По этой причине я могу инкапсулировать, используя!
или, в моем случае,?
с удерживающим устройством??
var b:Business = Business()
вне бокового цикла, он может отображать одни и те же данные в каждом элементе списка.для swift 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) } }
Пример использования:
let dict = myString.toJSON() as? [String:AnyObject] // can be any type here
источник
do-catch
, здесьtry?
можно использовать, что даст тот же результат, что и возврат nil вcatch
.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) } }
Простого расширения String должно хватить:
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 } } }
Потом:
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"; } */
источник
Swift 4 анализирует JSON намного элегантнее. Просто примените кодируемый протокол для своей структуры, как показано в этом упрощенном примере:
struct Business: Codable { let id: Int let name: String }
Чтобы проанализировать массив JSON, вы сообщаете декодеру, какие объекты массива данных
let parsedData = decoder.decode([Business].self, from: data)
Вот полный рабочий пример:
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)
Для получения дополнительной информации ознакомьтесь с этим отличным руководством .
источник
Для Swift 4
Я использовал логику @ Passkit , но мне пришлось обновить в соответствии с Swift 4
Шаг.1 Созданное расширение для класса 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 } } }
Шаг 2 Вот как я использовал в своем контроллере представления
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])")
Вся заслуга принадлежит первоначальному пользователю, я только что обновился до последней быстрой версии
источник
Я написал библиотеку, которая упрощает работу с данными json и десериализацию в Swift. Вы можете получить его здесь: https://github.com/isair/JSONHelper
Изменить: я обновил свою библиотеку, теперь вы можете сделать это только с помощью этого:
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 }
Старый ответ:
Во-первых, вместо использования .responseString используйте .response для получения объекта ответа. Затем измените свой код на:
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. } } }
А вот бизнес-класс нужно сделать так:
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"] } }
Вы можете найти полную документацию в моем репозитории GitHub. Радоваться, веселиться!
источник
Для Swift 4 я написал это расширение, используя протокол 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)
источник
Для
iOS 10
&Swift 3
с использованием 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") } }
и вот класс 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 } }
ИМО, это, безусловно, самое элегантное решение.
источник
let jsonString = "{\"id\":123,\"Name\":\"Munish\"}"
Преобразовать строку в NSData
var data: NSData =jsonString.dataUsingEncoding(NSUTF8StringEncoding)! var error: NSError?
Преобразование NSData в 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)")
источник
Мне нравится ответ RDC, но зачем ограничивать возвращаемый JSON только массивами на верхнем уровне? Мне нужно было разрешить словарь на верхнем уровне, поэтому я изменил его следующим образом:
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 } }
источник
SWIFT4 - простой и элегантный способ декодирования строк JSON в Struct.
Первый шаг - кодируйте String в Data с кодировкой .utf8.
Затем декодируйте ваши данные в 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 {}
источник
Вы можете использовать swift.quicktype.io для преобразования
JSON
вstruct
илиclass
. Даже вы можете упомянуть версию быстрой генерации кода.Пример JSON:
{ "message": "Hello, World!" }
Сгенерированный код:
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 } }
источник
Используя библиотеку SwiftyJSON , вы могли бы сделать это как
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) } } }
источник
Вот пример, который поможет вам упростить задачу. Мои строковые данные в моей базе данных - это файл JSON, который выглядит следующим образом:
[{"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"}]
Чтобы загрузить эти строковые данные JSON, выполните следующие простые шаги. Сначала создайте класс для моего объекта MoreData следующим образом:
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 }}
Во-вторых, создайте расширение String для моей строки JSON следующим образом:
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) }}
В-третьих, создайте класс My Srevices для обработки моих строковых данных следующим образом:
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 }}
Наконец, вызовите эту функцию из контроллера представления, чтобы загрузить данные в виде таблицы следующим образом:
func handlingJsonStringData(){ moreData.removeAll(keepingCapacity: false) moreData = Services.instance.loadMoreDataByString(byString: jsonString) print(self.moreData.count) tableView.reloadData() }
источник
Это может кому-то помочь. Аналогичный пример.
Это наш
Codable
класс для привязки данных. Вы можете легко создать этот класс с помощью 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) } }
Это строка Json
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\"}]"
Здесь мы конвертируем в быстрый объект.
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) }
источник
Используйте swiftyJson swiftyJson
platform :ios, '8.0' use_frameworks! target 'MyApp' do pod 'SwiftyJSON', '~> 4.0' end
Применение
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)
источник