parse - read json swift 4
JSON Parsing en Swift 3 (8)
JSON Parsing en swift 4 usando el protocolo decodificable:
Creo un archivo mocky usando su objeto json:
http://www.mocky.io/v2/5a280c282f0000f92c0635e6
Aquí está el código para analizar el JSON:
Creación del modelo:
import UIKit
struct Item : Decodable {
// Properties must be the same name as specified in JSON , else it will return nil
var Number : String
var Name : String
}
struct Language : Decodable {
var Field : [Item]
}
struct Result : Decodable {
var Language : Language
}
Puede usar opcional en el modelo si no está seguro de que algo pueda faltar en el archivo JSON.
Esta es la lógica de análisis:
class ViewController: UIViewController {
let url = "http://www.mocky.io/v2/5a280c282f0000f92c0635e6"
private func parseJSON() {
guard let url = URL(string: url) else { return }
let session = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
guard let result = try? JSONDecoder().decode(Result.self, from: data) else { return }
print("/n/nResult : /(result)")
}
session.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
parseJSON()
}
}
La salida de impresión:
Result : Result(Language: JSON_Parsing.Language(Field: [JSON_Parsing.Item(Number: "976", Name: "Test"), JSON_Parsing.Item(Number: "977", Name: "Test")]))
¿Alguien ha podido encontrar una forma de analizar a través de archivos JSON en Swift 3? He podido recuperar los datos pero no tengo éxito cuando se trata de dividir los datos en campos específicos. Publicaba el código de muestra pero he pasado por tantos métodos diferentes sin éxito y no he guardado ninguno. El formato básico que quiero analizar es algo como esto. Gracias por adelantado.
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
¿Has probado JSONSerialization.jsonObject(with:options:)
?
var jsonString = "{" +
"/"Language/": {" +
"/"Field/":[" +
"{" +
"/"Number/":/"976/"," +
"/"Name/":/"Test/"" +
"}," +
"{" +
"/"Number/":/"977/"," +
"/"Name/":/"Test/"" +
"}" +
"]" +
"}" +
"}"
var data = jsonString.data(using: .utf8)!
let json = try? JSONSerialization.jsonObject(with: data)
Swift a veces produce una sintaxis muy extraña.
if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
print(number)
}
Todo en la jerarquía de objetos JSON termina envuelto como opcional (es decir, AnyObject?
). Array<T>
subíndice Array<T>
devuelve una T
no opcional. Para este JSON, que está envuelto en un subíndice de matriz opcional, devuelve Optional<AnyObject>
. Sin embargo, el subíndice Dictionary<K, V>
devuelve un Optional<V>
. Para este JSON, el subíndice devuelve el aspecto muy extraño Optional<Optional<AnyObject>>
(es decir, AnyObject??
).
-
json
es unOptional<AnyObject>
. -
json?["Language"]
devuelve unOptional<Optional<AnyObject>>
. -
json?["Language"]??["Field"]
devuelve unOptional<Optional<AnyObject>>
. -
json?["Language"]??["Field"]??[0]
devuelve unOptional<AnyObject>
. -
json?["Language"]??["Field"]??[0]?["Number"]
devuelve unOptional<Optional<AnyObject>>
. -
json?["Language"]??["Field"]??[0]?["Number"] as? String
json?["Language"]??["Field"]??[0]?["Number"] as? String
devuelve unOptional<String>
.
El Optional<String>
es luego utilizado por la sintaxis if let
para producir un String
.
Nota final: la iteración de la matriz de campo se ve así.
for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
if let number = field["Number"] as? String {
print(number)
}
}
Swift 4 actualización
Swift 4 hace todo esto mucho más fácil de tratar. Nuevamente comenzaremos con sus datos de prueba ( """
hace mucho mejor").
let data = """
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
""".data(using: .utf8)!
Luego podemos definir clases alrededor de los objetos usados en su JSON.
struct Object: Decodable {
let language: Language
enum CodingKeys: String, CodingKey { case language="Language" }
}
struct Language: Decodable {
let fields: [Field]
enum CodingKeys: String, CodingKey { case fields="Field" }
}
struct Field: Decodable {
let number: String
let name: String
enum CodingKeys: String, CodingKey { case number="Number"; case name="Name" }
}
La enumeración de CodingKeys
es cómo se mapean las propiedades de estructura a las cadenas de miembros de objeto JSON. Este mapeo se hace automágicamente por Decodable
.
Analizar el JSON ahora es simple.
let object = try! JSONDecoder().decode(Object.self, from: data)
print(object.language.fields[0].name)
for field in object.language.fields {
print(field.number)
}
Análisis JSON usando Swift 4 en Simple WAY
let url = URL(string: "http://mobileappdevelop.co/TIPIT/webservice/get_my_groups?user_id=5")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
print(json)
let posts = json["Field"] as? [[String: Any]] ?? []
print(posts)
} catch let error as NSError {
print(error)
}
}).resume()
}
Empujar JSON en una cuerda manualmente es una pita. ¿Por qué no pones el JSON en un archivo y lo lees?
Swift 3:
let bundle = Bundle(for: type(of: self))
if let theURL = bundle.url(forResource: "response", withExtension: "json") {
do {
let data = try Data(contentsOf: theURL)
if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
grok(parsedData)
}
} catch {
print(error)
}
}
En Xcode 8 y Swift 3 id
ahora importa como Any
lugar de AnyObject
Esto significa que JSONSerialization.jsonObject(with: data)
devuelve Any
. Entonces debe convertir los data
json a un tipo específico como [String:Any]
. Lo mismo se aplica a los siguientes campos en el json.
var jsonString = "{" +
"/"Language/": {" +
"/"Field/":[" +
"{" +
"/"Number/":/"976/"," +
"/"Name/":/"Test1/"" +
"}," +
"{" +
"/"Number/":/"977/"," +
"/"Name/":/"Test2/"" +
"}" +
"]" +
"}" +
"}"
var data = jsonString.data(using: .utf8)!
if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
let language = parsedData["Language"] as! [String:Any]
print(language)
let field = language["Field"] as! [[String:Any]]
let name = field[0]["Name"]!
print(name) // ==> Test1
}
En la práctica, es probable que desee un campo específico enterrado en el json. Supongamos que es el campo Name
del primer elemento de la matriz de Field
. Puede usar una cadena de desenvolvimientos como esta para acceder de forma segura al campo:
var data = jsonString.data(using: .utf8)!
if let json = try? JSONSerialization.jsonObject(with: data) as? [String:Any],
let language = json?["Language"] as? [String:Any],
let field = language["Field"] as? [[String:Any]],
let name = field[0]["Name"] as? String, field.count > 0 {
print(name) // ==> Test1
} else {
print("bad json - do some recovery")
}
También es posible que desee comprobar Apple Swift Blog Trabajar con JSON en Swift
Usar la librería swiftjson, creo que es una manera muy fácil de analizar
let count: Int? = json["Field"].array?.count
if let ct = count {
for index in 0...ct-1{
let number = json ["Field"][index]["number"].string
let name = json ["Field"][index]["name"].string
....
Me gusta esto .
dict = {
message = "Login successfully.";
status = 1;
"user_details" = (
{
dob = "1900-11-18";
email = "[email protected]";
gender = male;
name = Rizwan;
nickname = Shaikh;
"profile_pic" = "1483434421.jpeg";
"social_id" = "<null>";
"user_id" = 2;
}
);
}
We can parse above json in swift 3 as
var dict2 = dict as! [String : Any]
print(dict);
let demoStr = dict2["message"] as! String
print(demoStr)
let demoArray = dict2["user_details"] as! [Any]
let demoDict = demoArray[0] as! [String:Any]
print(demoDict["dob"]!)
override func viewDidLoad() {
super.viewDidLoad()
let url=URL(string:"http://api.androidhive.info/contacts/")
do {
let allContactsData = try Data(contentsOf: url!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = allContacts["contacts"] {
for index in 0...arrJSON.count-1 {
let aObject = arrJSON[index] as! [String : AnyObject]
names.append(aObject["name"] as! String)
contacts.append(aObject["email"] as! String)
}
}
print(names)
print(contacts)
self.tableView.reloadData()
}
catch {
}
}