He estado buscando durante días para convertir una cadena JSON bastante simple en un tipo de objeto en Swift, pero sin éxito.
Aquí está el código para la llamada de servicio web:
func GetAllBusiness() {
Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
println(string)
}
}
Tengo una estructura rápida Business.swift:
struct Business {
var Id : Int = 0
var Name = ""
var Latitude = ""
var Longitude = ""
var Address = ""
}
Aquí está mi servicio de prueba implementado:
[
{
"Id": 1,
"Name": "A",
"Latitude": "-35.243256",
"Longitude": "149.110701",
"Address": null
},
{
"Id": 2,
"Name": "B",
"Latitude": "-35.240592",
"Longitude": "149.104843",
"Address": null
}
...
]
Sería un placer si alguien me guiara a través de esto.
Gracias.
AnyObject
por clave, solo asegúrate antes de bajar a String que no lo esnil
. Por esa razón, puedo incapsularlo usando!
o en mi caso?
con holdplace??
var b:Business = Business()
fuera del bucle lateral, entonces podría mostrar los mismos datos en cada elemento de la lista.para 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) } }
Ejemplo de uso:
let dict = myString.toJSON() as? [String:AnyObject] // can be any type here
fuente
do-catch
,try?
se puede usar aquí, lo que dará el mismo resultado que devolver nil incatch
.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) } }
Como una simple extensión de cadena debería ser suficiente:
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 } } }
Entonces:
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"; } */
fuente
Swift 4 analiza JSON de forma mucho más elegante. Simplemente adopte el protocolo codificable para su estructura según este ejemplo simplificado:
struct Business: Codable { let id: Int let name: String }
Para analizar la matriz JSON, le dice al decodificador cuáles son los objetos de la matriz de datos
let parsedData = decoder.decode([Business].self, from: data)
Aquí hay un ejemplo de trabajo completo:
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)
Para obtener más antecedentes, consulte esta excelente guía .
fuente
Para Swift 4
Usé la lógica de @ Passkit pero tuve que actualizar según Swift 4
Paso.1 Extensión creada para la clase 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 } } }
Paso.2 Así es como lo usé en mi controlador de vista
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])")
Todo el crédito es para el usuario original, acabo de actualizar a la última versión rápida
fuente
Escribí una biblioteca que hace que trabajar con datos json y deserialización sea muy sencillo en Swift. Puede obtenerlo aquí: https://github.com/isair/JSONHelper
Editar: actualicé mi biblioteca, ahora puedes hacerlo solo con esto:
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 }
Respuesta anterior:
Primero, en lugar de usar .responseString, use .response para obtener un objeto de respuesta. Luego cambie su código a:
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. } } }
Y necesitas hacer una clase ejecutiva como esta:
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"] } }
Puede encontrar la documentación completa en mi repositorio de GitHub. ¡Que te diviertas!
fuente
Para Swift 4 , escribí esta extensión usando el protocolo 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)
fuente
Para
iOS 10
&Swift 3
, usando 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") } }
y aquí está la clase Categoría
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 } }
En mi opinión, esta es, con mucho, la solución más elegante.
fuente
let jsonString = "{\"id\":123,\"Name\":\"Munish\"}"
Convertir cadena en NSData
var data: NSData =jsonString.dataUsingEncoding(NSUTF8StringEncoding)! var error: NSError?
Convierta NSData a 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)")
fuente
Me gusta la respuesta de RDC, pero ¿por qué limitar el JSON devuelto para tener solo matrices en el nivel superior? Necesitaba permitir un diccionario en el nivel superior, así que lo modifiqué así:
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 } }
fuente
SWIFT4 : una forma fácil y elegante de decodificar cadenas JSON en Struct.
Primer paso : codificar String en datos con codificación .utf8.
De decodificación de datos a su 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 {}
fuente
Puede usar swift.quicktype.io para convertir
JSON
astruct
oclass
. Incluso puede mencionar la versión de código swift to genrate.Ejemplo JSON:
{ "message": "Hello, World!" }
Código generado:
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 } }
fuente
Usando la biblioteca SwiftyJSON , podría hacerlo como
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) } } }
fuente
Aquí tienes una muestra para que las cosas sean más sencillas y fáciles. Los datos de mi cadena en mi base de datos son un archivo JSON que se ve así:
[{"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"}]
Para cargar estos datos de cadena JSON, siga estos sencillos pasos. Primero, cree una clase para mi objeto MoreData como este:
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 }}
En segundo lugar, cree mi extensión de cadena para mi cadena JSON de esta manera:
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) }}
En tercer lugar, cree My Srevices Class para manejar mis datos de cadena de esta manera:
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 }}
Finalmente, llame a esta función desde el controlador de vista para cargar datos en la vista de tabla de esta manera:
func handlingJsonStringData(){ moreData.removeAll(keepingCapacity: false) moreData = Services.instance.loadMoreDataByString(byString: jsonString) print(self.moreData.count) tableView.reloadData() }
fuente
Podría ayudar a alguien. Ejemplo similar.
Esta es nuestra
Codable
clase para vincular datos. Puede crear fácilmente esta clase usando 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) } }
Esto es 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\"}]"
Aquí lo convertimos en objeto rápido.
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) }
fuente