Hat jemand einen Weg gefunden, JSON-Dateien in Swift 3 zu analysieren? Ich konnte die Daten zurückgeben, ist jedoch nicht erfolgreich, wenn es darum geht, die Daten in bestimmte Felder zu unterteilen. Ich würde Beispielcode posten, aber ich habe so viele verschiedene Methoden durchlaufen und habe keine gespeichert. Das grundlegende Format, das ich analysieren möchte, ist so etwas. Danke im Voraus.
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
Haben Sie JSONSerialization.jsonObject(with:options:)
ausprobiert?
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 erzeugt manchmal eine sehr seltsame Syntax.
if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
print(number)
}
Alles in der JSON-Objekthierarchie wird als optionales Element eingeschlossen (dh AnyObject?
). Array<T>
subscript gibt eine nicht optionale T
zurück. Für diese JSON, die optional in einem Array eingeschlossen ist, gibt der Array-Index Optional<AnyObject>
zurück. Dictionary<K, V>
-Index gibt jedoch einen Optional<V>
zurück. Für diese JSON gibt das Subskription das sehr ungerade aussehende Optional<Optional<AnyObject>>
(dh AnyObject??
) zurück.
json
ist ein Optional<AnyObject>
.json?["Language"]
gibt einen Optional<Optional<AnyObject>>
zurück.json?["Language"]??["Field"]
gibt einen Optional<Optional<AnyObject>>
zurück.json?["Language"]??["Field"]??[0]
gibt einen Optional<AnyObject>
zurück.json?["Language"]??["Field"]??[0]?["Number"]
gibt einen Optional<Optional<AnyObject>>
zurück.json?["Language"]??["Field"]??[0]?["Number"] as? String
gibt einen Optional<String>
zurück.Der Optional<String>
wird dann von der if let
-Syntax verwendet, um eine String
zu erzeugen.
Schlussbemerkung: Das Durchlaufen des Feld-Arrays sieht folgendermaßen aus.
for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
if let number = field["Number"] as? String {
print(number)
}
}
Swift 4 Update
Mit Swift 4 ist das alles viel einfacher zu handhaben. Wieder beginnen wir mit Ihren Testdaten ("""
macht das so viel schöner).
let data = """
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
""".data(using: .utf8)!
Als Nächstes können wir Klassen um die in Ihrem JSON verwendeten Objekte definieren.
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" }
}
Die Aufzählung CodingKeys
gibt an, wie Struktureigenschaften JSON-Objektelementstrings zugeordnet werden. Diese Zuordnung wird automatisch von Decodable
durchgeführt.
Das Parsen des JSON ist jetzt einfach.
let object = try! JSONDecoder().decode(Object.self, from: data)
print(object.language.fields[0].name)
for field in object.language.fields {
print(field.number)
}
In Xcode 8 und Swift 3id
wird jetzt als Any
anstelle von AnyObject
importiert.
Dies bedeutet, dass JSONSerialization.jsonObject(with: data)
Any
zurückgibt. Sie müssen also die json data
in einen bestimmten Typ wie [String:Any]
umwandeln. Gleiches gilt für die nächsten Felder des 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
}
In der Praxis würden Sie wahrscheinlich ein bestimmtes Feld im Json begraben wollen. Nehmen wir an, es ist das Feld Name
des ersten Elements des Arrays Field
. Sie können eine Kette von Unwraps wie folgt verwenden, um sicher auf das Feld zuzugreifen:
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")
}
Vielleicht möchten Sie auch den Swift-Blog von Apple überprüfen Arbeiten mit JSON in Swift
JSON manuell in einen String zu schieben ist eine Pita. Warum legst du nicht einfach die JSON in eine Datei und liest das ein?
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)
}
}
Verwenden Sie die Bibliothek swiftjson Ich denke, es ist eine sehr einfache Methode zum Analysieren
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
....
so was .
JSON-Analyse mit Swift 4 in 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()
}
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 {
}
}
Ich erstelle eine mocky Datei mit Ihrem Json-Objekt:
http://www.mocky.io/v2/5a280c282f0000f92c0635e6
Hier ist der Code zum Parsen des JSON:
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
}
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()
}
}
Result : Result(Language: JSON_Parsing.Language(Field: [JSON_Parsing.Item(Number: "976", Name: "Test"), JSON_Parsing.Item(Number: "977", Name: "Test")]))