Suche…


Syntax

  • NSJSONSerialization.JSONObjectWithData (jsonData, Optionen: NSJSONReadingOptions) // Gibt ein Objekt aus jsonData zurück. Diese Methode löst bei einem Fehler aus.
  • NSJSONSerialization.dataWithJSONObject (jsonObject, Optionen: NSJSONWritingOptions) // Gibt NSData aus einem JSON-Objekt zurück. Übergeben Sie NSJSONWritingOptions.PrettyPrinted in Optionen für eine Ausgabe, die besser lesbar ist.

JSON-Serialisierung, Kodierung und Dekodierung mit Apple Foundation und der Swift Standard Library

Die JSONSerialization- Klasse ist in das Foundation-Framework von Apple integriert.

2.2

Lesen Sie JSON

Die JSONObjectWithData Funktion verwendet NSData und gibt AnyObject . Sie können as? um das Ergebnis in Ihren erwarteten Typ zu konvertieren.

do {
    guard let jsonData = "[\"Hello\", \"JSON\"]".dataUsingEncoding(NSUTF8StringEncoding) else {
        fatalError("couldn't encode string as UTF-8")
    }

    // Convert JSON from NSData to AnyObject
    let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
    
    // Try to convert AnyObject to array of strings
    if let stringArray = jsonObject as? [String] {
        print("Got array of strings: \(stringArray.joinWithSeparator(", "))")
    }
} catch {
    print("error reading JSON: \(error)")
}

Sie können options: .AllowFragments anstelle von options: [] , um das Lesen von JSON zuzulassen, wenn das Objekt der obersten Ebene kein Array oder Wörterbuch ist.

Schreibe JSON

Beim Aufruf von dataWithJSONObject wird ein JSON-kompatibles Objekt (verschachtelte Arrays oder Wörterbücher mit Zeichenfolgen, Zahlen und NSNull ) in als NSData kodierte NSData NSNull dataWithJSONObject konvertiert.

do {
    // Convert object to JSON as NSData
    let jsonData = try NSJSONSerialization.dataWithJSONObject(jsonObject, options: [])
    print("JSON data: \(jsonData)")
    
    // Convert NSData to String
    let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding)!
    print("JSON string: \(jsonString)")
} catch {
    print("error writing JSON: \(error)")
}

Sie können options: .PrettyPrinted anstelle von options: [] für das hübsche Drucken.

3,0

Gleiches Verhalten in Swift 3, jedoch mit anderer Syntax.

do {
    guard let jsonData = "[\"Hello\", \"JSON\"]".data(using: String.Encoding.utf8) else {
        fatalError("couldn't encode string as UTF-8")
    }
    
    // Convert JSON from NSData to AnyObject
    let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
    
    // Try to convert AnyObject to array of strings
    if let stringArray = jsonObject as? [String] {
        print("Got array of strings: \(stringArray.joined(separator: ", "))")
    }
} catch {
    print("error reading JSON: \(error)")
}

do {
    // Convert object to JSON as NSData
    let jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
    print("JSON data: \(jsonData)")

    // Convert NSData to String
    let jsonString = String(data: jsonData, encoding: .utf8)!
    print("JSON string: \(jsonString)")
} catch {
    print("error writing JSON: \(error)")
}

Hinweis: Das Folgende ist derzeit nur in Swift 4.0 und höher verfügbar.

Ab Swift 4.0 enthält die Swift-Standardbibliothek die Protokolle Encodable und Decodable , um einen standardisierten Ansatz für die Encodable und Decodable zu definieren. Die Übernahme dieser Protokolle ermöglicht Implementierungen der Encoder und Decoder Protokolle, die Ihre Daten verschlüsseln oder von einer externen Repräsentation wie JSON codieren oder decodieren. Die Konformität mit dem Codable Protokoll kombiniert die Protokolle Encodable und Decodable . Dies ist jetzt die empfohlene Methode, um JSON in Ihrem Programm zu behandeln.

Automatisch codieren und decodieren

Die einfachste Möglichkeit, einen Typ codierbar zu machen, besteht darin, seine Eigenschaften als Typen zu definieren, die bereits Codable . Diese Typen umfassen Standardbibliothekstypen wie String , Int und Double ; und Foundation-Typen wie Date , Data und URL . Wenn die Eigenschaften eines Typs codierbar sind, entspricht der Typ selbst automatisch der Codable indem er einfach die Konformität erklärt.

Betrachten Sie das folgende Beispiel, in dem die Book Struktur mit Codable .

struct Book: Codable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

Beachten Sie, dass Standardsammlungen wie Array und Dictionary mit Codable übereinstimmen, wenn sie codierbare Typen enthalten.

Durch die Codable von Codable kann die Book Struktur jetzt mit den Apple Foundation-Klassen JSONEncoder und JSONDecoder JSON codiert und daraus decodiert werden, obwohl Book selbst keinen Code für die spezifische Verarbeitung von JSON enthält. Benutzerdefinierte Encoder und Decoder können ebenfalls geschrieben werden, indem sie den Protokollen Encoder bzw. Decoder entsprechen.

In JSON-Daten kodieren

// Create an instance of Book called book
let encoder = JSONEncoder()
let data = try! encoder.encode(book) // Do not use try! in production code
print(data)

encoder.outputFormatting = .prettyPrinted Sie encoder.outputFormatting = .prettyPrinted um das Lesen zu erleichtern. ## Aus JSON-Daten dekodieren

Aus JSON-Daten decodieren

// Retrieve JSON string from some source
let jsonData = jsonString.data(encoding: .utf8)!
let decoder = JSONDecoder()
let book = try! decoder.decode(Book.self, for: jsonData) // Do not use try! in production code
print(book)

Im obigen Beispiel informiert Book.self den Decoder über den Typ, in den der JSON decodiert werden soll.

Ausschließlich kodieren oder dekodieren

In manchen Fällen müssen Daten möglicherweise nicht sowohl kodierbar als auch dekodierbar sein, z. B. wenn Sie nur JSON-Daten von einer API lesen oder Ihr Programm nur JSON-Daten an eine API sendet.

Wenn Sie nur JSON-Daten schreiben Encodable , Encodable Ihren Typ an Encodable .

struct Book: Encodable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

Wenn Sie nur JSON-Daten lesen Decodable , Decodable Ihren Typ an Decodable .

struct Book: Decodable {
    let title: String
    let authors: [String]
    let publicationDate: Date
}

Benutzerdefinierte Tastennamen verwenden

APIs verwenden häufig andere Namenskonventionen als den Kamel-Fall nach Swift-Standard, beispielsweise den Fall mit Schlangen. Dies kann zu einem Problem bei der Dekodierung von JSON werden, da die JSON-Schlüssel standardmäßig genau mit den Eigenschaftsnamen Ihres Typs übereinstimmen müssen. Um mit diesen Szenarien umgehen zu können, können Sie mithilfe des CodingKey Protokolls benutzerdefinierte Schlüssel für Ihren Typ CodingKey .

struct Book: Codable {
    // ...
    enum CodingKeys: String, CodingKey { 
        case title
        case authors
        case publicationDate = "publication_date"
    }
}

CodingKeys werden automatisch für Typen erzeugt , die das annehmen Codable Protokoll, sondern durch unsere eigene Implementierung in dem Beispiel die Schaffung oben wir zulassen , dass unsere Decoder den lokalen Kamel Fall übereinstimmen publicationDate mit der Schlange Fall publication_date wie sie von der API geliefert wird .

SwiftyJSON

SwiftyJSON ist ein Swift-Framework, das die Notwendigkeit einer optionalen Verkettung bei der normalen JSON-Serialisierung beseitigt.

Sie können es hier herunterladen: https://github.com/SwiftyJSON/SwiftyJSON

Ohne SwiftyJSON würde Ihr Code so aussehen, um den Namen des ersten Buches in einem JSON-Objekt zu finden:

if let jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]],
let bookName = (jsonObject[0]["book"] as? [String: AnyObject])?["name"] as? String {
    //We can now use the book name
}

In SwiftyJSON ist dies enorm vereinfacht:

let json = JSON(data: data)
if let bookName = json[0]["book"]["name"].string {
    //We can now use the book name
}

Dadurch entfällt die Notwendigkeit, jedes Feld zu überprüfen, da es null zurückgibt, wenn eines der Felder ungültig ist.

Um SwiftyJSON zu verwenden, laden Sie die korrekte Version aus dem Git-Repository herunter. Es gibt einen Zweig für Swift 3. Ziehen Sie einfach die "SwiftyJSON.swift" in Ihr Projekt und importieren Sie sie in Ihre Klasse:

import SwiftyJSON

Sie können Ihr JSON-Objekt mithilfe der folgenden zwei Initialisierer erstellen:

let jsonObject = JSON(data: dataObject)

oder

let jsonObject = JSON(jsonObject) //This could be a string in a JSON format for example

Um auf Ihre Daten zuzugreifen, verwenden Sie Indizes:

let firstObjectInAnArray = jsonObject[0]
let nameOfFirstObject = jsonObject[0]["name"]

Sie können Ihren Wert dann zu einem bestimmten Datentyp parsen, der einen optionalen Wert zurückgibt:

let nameOfFirstObject = jsonObject[0]["name"].string //This will return the name as a string

let nameOfFirstObject = jsonObject[0]["name"].double //This will return null

Sie können Ihre Pfade auch in ein schnelles Array kompilieren:

let convolutedPath = jsonObject[0]["name"][2]["lastName"]["firstLetter"].string

Ist das gleiche wie:

let convolutedPath = jsonObject[0, "name", 2, "lastName", "firstLetter"].string

SwiftyJSON bietet auch Funktionen zum Drucken eigener Fehler:

if let name = json[1337].string {
    //You can use the value - it is valid
} else {
    print(json[1337].error) // "Array[1337] is out of bounds" - You cant use the value
}

Wenn Sie in Ihr JSON-Objekt schreiben müssen, können Sie erneut Subskripte verwenden:

var originalJSON:JSON = ["name": "Jack", "age": 18]
originalJSON["age"] = 25 //This changes the age to 25
originalJSON["surname"] = "Smith" //This creates a new field called "surname" and adds the value to it

Wenn Sie den ursprünglichen String für den JSON benötigen, zum Beispiel, wenn Sie ihn in eine Datei schreiben müssen, können Sie den Rohwert erhalten:

if let string = json.rawString() { //This is a String object
    //Write the string to a file if you like
}

if let data = json.rawData() { //This is an NSData object
    //Send the data to your server if you like
}

Freddy

Freddy ist eine JSON-Parsing-Bibliothek, die von der Big Nerd Ranch verwaltet wird . Es hat drei Hauptvorteile:

  1. Typensicherheit: Hilft Ihnen beim Senden und Empfangen von JSON auf eine Weise, die Laufzeitabstürze verhindert.

  2. Idiomatic: Nutzen Sie die Generika, Aufzählungen und Funktionsmerkmale von Swift, ohne komplizierte Dokumentation oder magische benutzerdefinierte Operatoren.

  3. Fehlerbehandlung: Enthält informative Fehlerinformationen für häufig auftretende JSON-Fehler.

Beispiel JSON-Daten

Definieren wir einige JSON-Beispieldaten für diese Beispiele.

{
  "success": true,
  "people": [
    {
      "name": "Matt Mathias",
      "age": 32,
      "spouse": true
    },
    {
      "name": "Sergeant Pepper",
      "age": 25,
      "spouse": false
    }
  ],
  "jobs": [
    "teacher",
    "judge"
  ],
  "states": {
    "Georgia": [
      30301,
      30302,
      30303
    ],
    "Wisconsin": [
      53000,
      53001
    ]
  }
}
let jsonString = "{\"success\": true, \"people\": [{\"name\": \"Matt Mathias\",\"age\": 32,\"spouse\": true},{\"name\": \"Sergeant Pepper\",\"age\": 25,\"spouse\": false}],\"jobs\": [\"teacher\",\"judge\"],\"states\": {\"Georgia\": [30301,30302,30303],\"Wisconsin\": [53000,53001]}}"
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!

Rohdaten deserialisieren

Um die Daten zu deserialisieren, initialisieren wir ein JSON Objekt und greifen dann auf einen bestimmten Schlüssel zu.

do {
    let json = try JSON(data: jsonData)
    let success = try json.bool("success")
} catch {
    // do something with the error
}

Wir try hier, weil der Zugriff auf den json für den Schlüssel "success" fehlschlagen könnte - er existiert möglicherweise nicht oder der Wert ist möglicherweise nicht boolean.

Wir können auch einen Pfad angeben, um auf Elemente zuzugreifen, die in der JSON-Struktur verschachtelt sind. Der Pfad ist eine durch Kommas getrennte Liste von Schlüsseln und Indizes, die den Pfad zu einem interessierenden Wert beschreiben.

do {
    let json = try JSON(data: jsonData)
    let georgiaZipCodes = try json.array("states", "Georgia")
    let firstPersonName = try json.string("people", 0, "name")
} catch {
    // do something with the error
}

Modelle direkt deserialisieren

JSON kann direkt in eine Modellklasse analysiert werden, die das JSONDecodable Protokoll implementiert.

public struct Person {
    public let name: String
    public let age: Int
    public let spouse: Bool
}

extension Person: JSONDecodable {
    public init(json: JSON) throws {
        name = try json.string("name")
        age = try json.int("age")
        spouse = try json.bool("spouse")
    }
}

do {
    let json = try JSON(data: jsonData)
    let people = try json.arrayOf("people", type: Person.self)
} catch {
    // do something with the error
}

Serialisierung von Rohdaten

Jeder JSON Wert kann direkt in NSData serialisiert werden.

let success = JSON.Bool(false)
let data: NSData = try success.serialize()

Direktes Serialisieren von Modellen

Jede Modellklasse, die das JSONEncodable Protokoll implementiert, kann direkt in NSData serialisiert werden.

extension Person: JSONEncodable {
    public func toJSON() -> JSON {
        return .Dictionary([
            "name": .String(name),
            "age": .Int(age),
            "spouse": .Bool(spouse)
        ])
    }
}

let newPerson = Person(name: "Glenn", age: 23, spouse: true)
let data: NSData = try newPerson.toJSON().serialize()

Pfeil

Arrow ist eine elegante JSON-Parsing-Bibliothek in Swift.

Es erlaubt, JSON zu parsen und mit Hilfe eines <-- Operators benutzerdefinierten Modellklassen zuzuordnen:

identifier <-- json["id"]
name <-- json["name"]
stats <-- json["stats"]

Beispiel:

Schnelles Modell

struct Profile {
    var identifier = 0
    var name = ""
    var link: NSURL?
    var weekday: WeekDay = .Monday
    var stats = Stats()
    var phoneNumbers = [PhoneNumber]()
}

JSON-Datei

{
    "id": 15678,
    "name": "John Doe",
    "link": "https://apple.com/steve",
    "weekdayInt" : 3,
    "stats": {
        "numberOfFriends": 163,
        "numberOfFans": 10987
    },
    "phoneNumbers": [{
                     "label": "house",
                     "number": "9809876545"
                     }, {
                     "label": "cell",
                     "number": "0908070656"
                     }, {
                     "label": "work",
                     "number": "0916570656"
    }]
}

Kartierung

extension Profile: ArrowParsable {
    mutating func deserialize(json: JSON) {
        identifier <-- json["id"]
        link <-- json["link"]
        name <-- json["name"]
        weekday <-- json["weekdayInt"]
        stats <- json["stats"]
        phoneNumbers <-- json["phoneNumbers"]
    }
}

Verwendungszweck

let profile = Profile()
profile.deserialize(json)

Installation:

Karthago

github "s4cha/Arrow"

Kakaopods

pod 'Arrow'
use_frameworks!

Manuell

Kopieren Sie einfach Arrow.swift in Ihr Xcode-Projekt

https://github.com/s4cha/Arrow

Als Rahmen

Laden Sie Arrow aus dem GitHub-Repository herunter und erstellen Sie das Framework-Ziel für das Beispielprojekt. Dann Link gegen diesen Rahmen.

Einfache JSON-Analyse in benutzerdefinierte Objekte

Selbst wenn Bibliotheken von Drittanbietern gut sind, bieten Protokolle eine einfache Möglichkeit zum Analysieren der JSON. Sie können sich vorstellen, dass Sie ein Objekt als Todo

struct Todo {
    let comment: String
}

Wenn Sie den JSON erhalten, können Sie die einfachen NSData wie im anderen Beispiel mit dem NSJSONSerialization Objekt behandeln.

Danach mit einem einfachen Protokoll JSONDecodable

typealias JSONDictionary = [String:AnyObject]
protocol JSONDecodable {
    associatedtype Element
    static func from(json json: JSONDictionary) -> Element?
}

Und JSONDecodable Ihre Todo Struktur JSONDecodable konform machen, können JSONDecodable dies JSONDecodable

extension Todo: JSONDecodable {
    static func from(json json: JSONDictionary) -> Todo? {
        guard let comment = json["comment"] as? String else { return nil }
        return Todo(comment: comment)
    }
}

Sie können es mit diesem Json-Code versuchen:

{
    "todos": [
        {
            "comment" : "The todo comment"
        }
    ]
}

Wenn Sie es von der API erhalten haben, können Sie es wie in den vorherigen Beispielen in einer AnyObject Instanz AnyObject . Danach können Sie überprüfen, ob es sich bei der Instanz um eine JSONDictionary Instanz handelt

guard let jsonDictionary = dictionary as? JSONDictionary else { return }

Die andere Sache, die speziell für diesen Fall geprüft werden muss, weil Sie ein Todo Array in der JSON haben, ist das todos Wörterbuch

guard let todosDictionary = jsonDictionary["todos"] as? [JSONDictionary] else { return }

Nun , da Sie das Array von Wörterbüchern erhalten haben, können Sie jede von ihnen in einem konvertieren Todo Objekt unter Verwendung flatMap (es wird automatisch die löschen nil Werte aus dem Array)

let todos: [Todo] = todosDictionary.flatMap { Todo.from(json: $0) }

JSON Parsing Swift 3

Hier ist die JSON-Datei, die wir als animals.json

{
    "Sea Animals": [
    {
     "name": "Fish",
     "question": "How many species of fish are there?"    },
                {
                "name": "Sharks",
                "question": "How long do sharks live?"
                },
                {
                "name": "Squid",
                "question": "Do squids have brains?"
                },
                {
                "name": "Octopus",
                "question": "How big do octopus get?"
                },
                {
                "name": "Star Fish",
                "question": "How long do star fish live?"
                }
                ],
    "mammals": [
                {
      "name": "Dog",
      "question": "How long do dogs live?"
    },
    {
      "name": "Elephant",
      "question": "How much do baby elephants weigh?"
    },
    {
      "name": "Cats",
      "question": "Do cats really have 9 lives?"
    },
    {
      "name": "Tigers",
      "question": "Where do tigers live?"
    },
    {
      "name": "Pandas",
      "question": "WHat do pandas eat?"
    }   ] }

Importieren Sie Ihre JSON-Datei in Ihr Projekt

Sie können diese einfache Funktion ausführen, um Ihre JSON-Datei auszudrucken

   func jsonParsingMethod() {
        //get the file
        let filePath = Bundle.main.path(forResource: "animals", ofType: "json")
        let content = try! String(contentsOfFile: filePath!)
        
        let data: Data = content.data(using: String.Encoding.utf8)!
        let json: NSDictionary =  try! JSONSerialization.jsonObject(with: data as Data, options:.mutableContainers) as! NSDictionary
      
//Call which part of the file you'd like to pare
        if let results = json["mammals"] as? [[String: AnyObject]] {
            
            for res in results {
                //this will print out the names of the mammals from out file.
                if let rates = res["name"] as? String {
                    print(rates)
                }
           }
       }
    }

Wenn Sie es in eine Tabellenansicht einfügen möchten, würde ich zuerst ein Wörterbuch mit einem NSObject erstellen.

Erstellen Sie eine neue Swift-Datei mit dem Namen ParsingObject und erstellen Sie Ihre String-Variablen.

Stellen Sie sicher, dass der Variablenname der JSON-Datei entspricht

. Zum Beispiel haben wir in unserem Projekt einen name und eine question so dass wir sie in unserer neuen Swift-Datei verwenden werden

var name: String?
var question: String?

Initialisieren Sie das NSObject, das wir in ViewController.swift erstellt haben. Var array = ParsingObject Dann würden wir dieselbe Methode ausführen, die wir zuvor mit einer geringfügigen Modifikation verwendet haben.

     func jsonParsingMethod() {
            //get the file
            let filePath = Bundle.main.path(forResource: "animals", ofType: "json")
            let content = try! String(contentsOfFile: filePath!)
            
            let data: Data = content.data(using: String.Encoding.utf8)!
            let json: NSDictionary =  try! JSONSerialization.jsonObject(with: data as Data, options:.mutableContainers) as! NSDictionary
            
//This time let's get Sea Animals
            let results = json["Sea Animals"] as? [[String: AnyObject]]
            
//Get all the stuff using a for-loop
            for i in 0 ..< results!.count {
                
//get the value
                let dict = results?[i]
                let resultsArray = ParsingObject()
                
//append the value to our NSObject file
                resultsArray.setValuesForKeys(dict!)
                array.append(resultsArray)
                
            }
          
        }

Dann zeigen wir es in unserer Tabellenansicht,

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return array.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//This is where our values are stored
            let object = array[indexPath.row]
            cell.textLabel?.text = object.name
            cell.detailTextLabel?.text = object.question
            return cell
        }


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow