jsonserialization - Leer en un archivo JSON usando Swift
recorrer json swift (18)
Realmente estoy luchando con intentar leer un archivo JSON en Swift para poder jugar con él. Pasé la mayor parte de 2 días rebuscando e intentando diferentes métodos, pero aún no tuve suerte, así que me he registrado en StackOverFlow para ver si alguien puede indicarme la dirección correcta ...
Mi archivo JSON se llama test.json y contiene lo siguiente:
{
"person":[
{
"name": "Bob",
"age": "16",
"employed": "No"
},
{
"name": "Vinny",
"age": "56",
"employed": "Yes"
}
]
}
El archivo se almacena directamente en los documentos y accedo al mismo usando el siguiente código:
let file = "test.json"
let dirs : String[] = NSSearchPathForDirectoriesInDomains(
NSSearchpathDirectory.DocumentDirectory,
NSSearchPathDomainMask.AllDomainMask,
true) as String[]
if (dirs != nil) {
let directories: String[] = dirs
let dir = directories[0]
let path = dir.stringByAppendingPathComponent(file)
}
var jsonData = NSData(contentsOfFile:path, options: nil, error: nil)
println("jsonData /(jsonData)" // This prints what looks to be JSON encoded data.
var jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as? NSDictionary
println("jsonDict /(jsonDict)") - This prints nil.....
Si alguien me puede dar un empujón en la dirección correcta sobre cómo puedo deserializar el archivo JSON y ponerlo en un objeto Swift accesible, ¡estaré eternamente agradecido!
Saludos cordiales,
Krivvenz.
Swift 3.0, Xcode 8, iOS 10
if let path = Bundle.main.url(forResource: "person", withExtension: "json") {
do {
let jsonData = try Data(contentsOf: path, options: .mappedIfSafe)
do {
if let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? NSDictionary {
if let personArray = jsonResult.value(forKey: "person") as? NSArray {
for (_, element) in personArray.enumerated() {
if let element = element as? NSDictionary {
let name = element.value(forKey: "name") as! String
let age = element.value(forKey: "age") as! String
let employed = element.value(forKey: "employed") as! String
print("Name: /(name), age: /(age), employed: /(employed)")
}
}
}
}
} catch let error as NSError {
print("Error: /(error)")
}
} catch let error as NSError {
print("Error: /(error)")
}
}
Salida:
Name: Bob, age: 16, employed: No
Name: Vinny, age: 56, employed: Yes
Aquí está mi solución usando SwiftyJSON
if let path : String = NSBundle.mainBundle().pathForResource("filename", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
let json = JSON(data: data)
}
}
Esto funcionó muy bien conmigo
func readjson(fileName: String) -> NSData{
let path = NSBundle.mainBundle().pathForResource(fileName, ofType: "json")
let jsonData = NSData(contentsOfMappedFile: path!)
return jsonData!
}
Esto funcionó para mí con XCode 8.3.3
func fetchPersons(){
if let pathURL = Bundle.main.url(forResource: "Person", withExtension: "json"){
do {
let jsonData = try Data(contentsOf: pathURL, options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as! [String: Any]
if let persons = jsonResult["person"] as? [Any]{
print(persons)
}
}catch(let error){
print (error.localizedDescription)
}
}
}
He usado el código siguiente para buscar JSON del archivo FAQ-data.json presente en el directorio del proyecto.
Estoy implementando en Xcode 7.3 usando Swift.
func fetchJSONContent() {
if let path = NSBundle.mainBundle().pathForResource("FAQ-data", ofType: "json") {
if let jsonData = NSData(contentsOfFile: path) {
do {
if let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary {
if let responseParameter : NSDictionary = jsonResult["responseParameter"] as? NSDictionary {
if let response : NSArray = responseParameter["FAQ"] as? NSArray {
responseFAQ = response
print("response FAQ : /(response)")
}
}
}
}
catch { print("Error while parsing: /(error)") }
}
}
}
override func viewWillAppear(animated: Bool) {
fetchFAQContent()
}
Estructura del archivo JSON:
{
"status": "00",
"msg": "FAQ List ",
"responseParameter": {
"FAQ": [
{
"question": “Question No.1 here”,
"answer": “Answer goes here”,
"id": 1
},
{
"question": “Question No.2 here”,
"answer": “Answer goes here”,
"id": 2
}
. . .
]
}
}
Nombres actualizados para Swift 3.0
Basado en la respuesta de Abhishek y la respuesta de Druva
func loadJson(forFilename fileName: String) -> NSDictionary? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
if let data = NSData(contentsOf: url) {
do {
let dictionary = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as? NSDictionary
return dictionary
} catch {
print("Error!! Unable to parse /(fileName).json")
}
}
print("Error!! Unable to load /(fileName).json")
}
return nil
}
Proporciono otra respuesta porque ninguno de los que están aquí está orientado a cargar el recurso del paquete de prueba. Si está consumiendo un servicio remoto que emite JSON y desea probar la unidad analizando los resultados sin acceder al servicio real, debe tomar una o más respuestas y colocarlas en los archivos de la carpeta Pruebas de su proyecto.
func testCanReadTestJSONFile() {
let path = NSBundle(forClass: ForecastIOAdapterTests.self).pathForResource("ForecastIOSample", ofType: "json")
if let jsonData = NSData(contentsOfFile:path!) {
let json = JSON(data: jsonData)
if let currentTemperature = json["currently"]["temperature"].double {
println("json: /(json)")
XCTAssertGreaterThan(currentTemperature, 0)
}
}
}
Esto también usa SwiftyJSON pero la lógica central de obtener el paquete de prueba y cargar el archivo es la respuesta a la pregunta.
SWIFTYJSON VERSIÓN SWIFT 3
func loadJson(fileName: String) -> JSON {
var dataPath:JSON!
if let path : String = Bundle.main.path(forResource: fileName, ofType: "json") {
if let data = NSData(contentsOfFile: path) {
dataPath = JSON(data: data as Data)
}
}
return dataPath
}
Según la respuesta de Abhishek , para iOS 8 esto sería:
let masterDataUrl: NSURL = NSBundle.mainBundle().URLForResource("masterdata", withExtension: "json")!
let jsonData: NSData = NSData(contentsOfURL: masterDataUrl)!
let jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: nil) as! NSDictionary
var persons : NSArray = jsonResult["person"] as! NSArray
Si alguien está buscando SwiftyJSON responda:
Actualizar:
Para Swift 3/4
:
if let path = Bundle.main.path(forResource: "assets/test", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped)
let jsonObj = try JSON(data: data)
print("jsonData:/(jsonObj)")
} catch let error {
print("parse error: /(error.localizedDescription)")
}
} else {
print("Invalid filename/path.")
}
Siga el siguiente código:
if let path = NSBundle.mainBundle().pathForResource("test", ofType: "json")
{
if let jsonData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)
{
if let jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary
{
if let persons : NSArray = jsonResult["person"] as? NSArray
{
// Do stuff
}
}
}
}
La matriz "personas" contendrá todos los datos para la persona clave. Iterar a través de para buscarlo.
Swift 4.0:
if let path = Bundle.main.path(forResource: "test", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
if let jsonResult = jsonResult as? Dictionary<String, AnyObject>, let person = jsonResult["person"] as? [Any] {
// do stuff
}
} catch {
// handle error
}
}
Swift 2.1 respuesta (basado en Abhishek):
if let path = NSBundle.mainBundle().pathForResource("test", ofType: "json") {
do {
let jsonData = try NSData(contentsOfFile: path, options: NSDataReadingOptions.DataReadingMappedIfSafe)
do {
let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let people : [NSDictionary] = jsonResult["person"] as? [NSDictionary] {
for person: NSDictionary in people {
for (name,value) in person {
print("/(name) , /(value)")
}
}
}
} catch {}
} catch {}
}
También podría recomendar el Swift JSON Tutorial de Ray Wenderlich (que también cubre la increíble alternativa de SwiftyJSON, Gloss ). Un extracto (que, por sí solo, no responde completamente al póster, pero el valor agregado de esta respuesta es el enlace, por lo que no hay -1 para eso):
En Objective-C, analizar y deserializar JSON es bastante sencillo:
NSArray *json = [NSJSONSerialization JSONObjectWithData:JSONData
options:kNilOptions error:nil];
NSString *age = json[0][@"person"][@"age"];
NSLog(@"Dani''s age is %@", age);
En Swift, analizar y deserializar JSON es un poco más tedioso debido a las opciones opcionales de Swift y la seguridad de tipo [pero como] parte de Swift 2.0, la declaración de
guard
se introdujo para ayudar a deshacerse de declaracionesif
anidadas:
var json: Array!
do {
json = try NSJSONSerialization.JSONObjectWithData(JSONData, options: NSJSONReadingOptions()) as? Array
} catch {
print(error)
}
guard let item = json[0] as? [String: AnyObject],
let person = item["person"] as? [String: AnyObject],
let age = person["age"] as? Int else {
return;
}
print("Dani''s age is /(age)")
Por supuesto, en XCode 8.x, solo toca dos veces la barra espaciadora y dice "Oye, Siri, deserializa este JSON para mí en Swift 3.0 con espacio / tabulaciones".
Último swift 3.0 trabajando absolutamente
func loadJson(filename fileName: String) -> [String: AnyObject]?
{
if let url = Bundle.main.url(forResource: fileName, withExtension: "json")
{
if let data = NSData(contentsOf: url) {
do {
let object = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
return dictionary
}
} catch {
print("Error!! Unable to parse /(fileName).json")
}
}
print("Error!! Unable to load /(fileName).json")
}
return nil
}
Actualizado para Swift 3 con la forma más segura
private func readLocalJsonFile() {
if let urlPath = Bundle.main.url(forResource: "test", withExtension: "json") {
do {
let jsonData = try Data(contentsOf: urlPath, options: .mappedIfSafe)
if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? [String: AnyObject] {
if let personArray = jsonDict["person"] as? [[String: AnyObject]] {
for personDict in personArray {
for (key, value) in personDict {
print(key, value)
}
print("/n")
}
}
}
}
catch let jsonError {
print(jsonError)
}
}
}
Swift 4 usando Decodable
struct ResponseData: Decodable {
var person: [Person]
}
struct Person : Decodable {
var name: String
var age: String
var employed: String
}
func loadJson(filename fileName: String) -> [Person]? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let jsonData = try decoder.decode(ResponseData.self, from: data)
return jsonData.person
} catch {
print("error:/(error)")
}
}
return nil
}
Swift 3
func loadJson(filename fileName: String) -> [String: AnyObject]? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let object = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
return dictionary
}
} catch {
print("Error!! Unable to parse /(fileName).json")
}
}
return nil
}
Xcode 8 Swift 3 lee json desde la actualización del archivo:
if let path = Bundle.main.path(forResource: "userDatabseFakeData", ofType: "json") {
do {
let jsonData = try NSData(contentsOfFile: path, options: NSData.ReadingOptions.mappedIfSafe)
do {
let jsonResult: NSDictionary = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
if let people : [NSDictionary] = jsonResult["person"] as? [NSDictionary] {
for person: NSDictionary in people {
for (name,value) in person {
print("/(name) , /(value)")
}
}
}
} catch {}
} catch {}
}
fileprivate class BundleTargetingClass {}
func loadJSON<T>(name: String) -> T? {
guard let filePath = Bundle(for: BundleTargetingClass.self).url(forResource: name, withExtension: "json") else {
return nil
}
guard let jsonData = try? Data(contentsOf: filePath, options: .mappedIfSafe) else {
return nil
}
guard let json = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) else {
return nil
}
return json as? T
}
👆🏻 copiar y pegar listo, solución independiente de marco de terceros.
uso 👇🏻
let json:[[String : AnyObject]] = loadJSON(name: "Stations")!