Swift JSONEncoder

Aus Wikizone
Wechseln zu: Navigation, Suche

Links[Bearbeiten]

Swift (Programmiersprache)
Swift - Decodable & Encodable

Beispiele[Bearbeiten]

Speichern von JSON Daten mit File I/O[Bearbeiten]

Siehe auch Swift JSONEncoder

struct Setlist: Codable {
    var title: String = "Default"
    var songs = [Song]()

    mutating func addSong(title: String, frequency: Float){
        print("Setlist::addSong")
        songs.append(Song(title:title, frequency: frequency))
    }
}

struct Song: Codable {
    let title: String
    let frequency: Float
}

// convert Setlist to json Data
let setlist = Setlist()
setlist.addSong(title: "song1", frequency: 44.1)
let encoder = JSONEncoder()
guard let encoded = try? encoder.encode(setlist) else {
    print("Encoding Failed")
    return
}

// write json Data to file
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent("setlist.json")
do {
    try encoded.write(to: fileURL, options: .atomic)
} catch {
    print("Error saving file: \(error)")
}

In diesem Beispiel wird die JSONEncoder Klasse verwendet, um eine Instanz des Structs Setlist in ein JSON-kodiertes Data-Objekt umzuwandeln. Das erzeugte JSON-kodierte Data wird in einer Datei gespeichert . In diesem Fall wird die Datei "setlist.json" im Dokumentenverzeichnis des Geräts gespeichert. Es ist zu beachten, dass es je nach Anwendungsfall sinnvoll sein kann, die Daten an einem anderen Ort oder in einem anderen Format zu speichern.

JSON Data Objekt als String ausgeben[Bearbeiten]

if let jsonString = String(data: encoded, encoding: .utf8) {
    print(jsonString)
} else {
    print("Could not convert encoded Data to String")
}

Dieser Code verwendet encoded Data und wandelt es in einen String um, indem es es decodiert und UTF-8 als Encoding verwendet. Wenn die Konvertierung erfolgreich ist, wird der Inhalt des Strings auf der Konsole ausgegeben. Es ist zu beachten, dass der JSON String nicht immer lesbar ausfällt, da die Reihenfolge der Werte innerhalb des Objekts oder des Arrays unvorhersehbar ist.

Ausführliches Beispiel mit Fehlerbehandlung[Bearbeiten]

Hier werden Daten von openWeather verarbeitet. Es gibt ein Struct, das auf die JSON Daten angepasst ist.

// WeatherData for decoding JSON
import Foundation

struct WeatherData: Codable{
    let name: String
    let main: Main
    let weather: [Weather]
}

struct Main: Codable{
    let temp: Double
}
struct Weather: Codable{
    let description: String
    let id: Int
}

In WeatherManager gibe es ein delegate protocol um später die Infos / Fehler weiterzugeben

Das JSON Parsing nutzt ein WeatherData Objekt um die JSON Infos darin zu speichern.

import Foundation
import CoreLocation

protocol WeatherManagerDelegate{
    func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
    func didFailWithError(error: Error)
}

struct WeatherManager{
    
    let weatherURL = "https://api.openweathermap.org/data/2.5/weather?units=metric&appid=63981dbcfa548021dd77394d24f34674"
    
    var delegate: WeatherManagerDelegate?
    
    func fetchWeather(cityName: String){
        let urlString = "\(weatherURL)&q=\(cityName)"
        performRequest(with: urlString)
    }
    
    func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees){
        let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
        performRequest(with: urlString)
    }
    
    func performRequest(with urlString: String){
        // 1. create URL
        let allowedCharacters = CharacterSet.urlQueryAllowed
        let encodedString = urlString.addingPercentEncoding(withAllowedCharacters: allowedCharacters) ?? ""
        if let url = URL(string: encodedString) {
            // 2. create URLSession
            let session = URLSession(configuration: .default)
            // 3. give session a task
            let task = session.dataTask(with: url) { data, response, error in
                if error != nil {
                    delegate?.didFailWithError(error: error!)
                    return
                }
                if let safeData = data {
                    if let weather = self.parseJSON(safeData){
                        self.delegate?.didUpdateWeather(self, weather: weather)
                    }
                }
            }
            // 4. start the task
            task.resume()
        }
    }
    
    func parseJSON(_ weatherData: Data)->WeatherModel? {
        let decoder = JSONDecoder()
        // decode needs a type not an object as parameter. We refer to the type with .self i.e. WeatherData.self
        do {
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
            let id = decodedData.weather[0].id
            let temp = decodedData.main.temp
            let name = decodedData.name
            
            let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp)
            
            print( "weatherName (sf-symbol): \(weather.conditionName)")
            print( "temperature: \(weather.temperatureStr)")
            
            return weather
            
        } catch {
            //print("Error parsing JSON: \(error)")
            delegate?.didFailWithError(error: error)
            return nil
        }
    }
    
    
    
}