JSON è ormai utilizzato diffusamente come formato di interscambio dati su internet. È molto comune per uno sviluppatore lavorare con JSON, specie se si tratta di app per smartphone.
In Swift 4 è stato introdotto il protocol Codable come parte del framework Foundation e serializzare o deserializzare un oggetto in JSON richiede tre linee di codice ;).
Le nuove API disponibili nel framework Foundation sono state presentate al WWDC 2017, vi consiglio di guardare il video a questo link: What’s New in Foundation (le API di cui sto parlando vengono illustrate dal minuto 23 in poi).
Vediamo come è diventato immediato e semplice convertire un oggetto in JSON e viceversa.
Implementare il protocol Codable, permette ai nostri dati di essere serializzati per diversi tipi di rappresentazione dati. Riguardo la codifica in JSON, le API ci rendono disponibile tutto il necessario.
L’unica cosa che dobbiamo fare è indicare che il nostro modello è conforme al protocol Codable.
Per iniziare creiamo un Playground su Xcode (per iOS o macOS non importa, le API sono in Foundation). Se hai un iPad (con iOS 11), puoi provare questo esempio anche sull’App Playgrounds.
Per i test proveremo a fare una richiesta GET ad un endpoint REST di test e decodificare la risposta JSON del webservice.
Come endpoint useremo quello disponibile in questo sito: https://jsonplaceholder.typicode.com.
NB: il task di URLSession è asincrono, quindi dobbiamo fare in modo che il Playground continui l’esecuzione indefinitivamente. Per fare questo aggiungiamo queste righe all’inizio del codice sorgente:
import PlaygroundSupport PlaygroundPage.current.needsIndefiniteExecution = true
Definiamo ora il nostro modello:
struct UserPost { var userId: Int? var id: Int? var title: String? var body: String? }
Adesso arriva la parte difficile! Dobbiamo fare in modo che la nostra struct sia conforme al protocol Codable e che sia possibile codificarla in JSON.
struct UserPost: Codable { var userId: Int? var id: Int? var title: String? var body: String? }
Fatto! È sufficiente indicare che implementiamo il protocol Codable.
Se non viene indicato diversamente, ogni nome di proprietà deve corrispondere alle chiavi della stringa JSON da decodificare.
Decodifica
La decodifica richiede giusto due righe di codice:
let decoder = JSONDecoder() guard let userPost = try? decoder.decode(UserPost.self, from: jsonString) else { return }
Proviamo subito, interrogando il servizio remoto: https://jsonplaceholder.typicode.com/posts/1 e decodificando la risposta.
import Foundation import PlaygroundSupport PlaygroundPage.current.needsIndefiniteExecution = true struct UserPost: Codable { var userId: Int? var id: Int? var title: String? var body: String? } let task = URLSession.shared.dataTask(with: URL(string: "https://jsonplaceholder.typicode.com/posts/1")!) { data, response, error in let decoder = JSONDecoder() guard error == nil, let data = data, let userPost = try? decoder.decode(UserPost.self, from: data) else { return } print("USER: \(userPost.userId ?? -1)") print("ID: \(userPost.id ?? -1)") print("TITLE: \(userPost.title ?? "")") print("BODY: \(userPost.body ?? "")") } task.resume()
Eseguendo il nostro Playground (hai provato a scriverlo sull’app Playground sul tuo iPad?), otterremo questo output:
USER: 1 ID: 1 TITLE: sunt aut facere repellat provident occaecati excepturi optio reprehenderit BODY: quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto
Personalizzare il nome delle proprietà del nostro modello
In alcuni casi può essere utile (o necessario) indicare un nome di proprietà che non corrisponde a nessuna chiave della rappresentazione JSON. Se vogliamo indicare un nome personalizzato, è sufficiente indicarlo in una enum CodingKeys all’interno del nostro modello. In questo caso vanno indicate tutte le proprietà, anche quelle che non è necessario personalizzare.
Se ad esempio un webservice ci restituisce una stringa JSON di questo tipo:
{ "id":1, "user_message":"Hello, World!", "count":4, "antani":"bitumata" }
Vogliamo evitare di scrivere una proprietà user_post, preferendo scriverla in camel case userPost. Il nostro modello diventerà:
struct AntaniModel: Codable { var id: Int? var userMessage: String? var count: Int? var antani: String? enum CodingKeys: String, CodingKey { case id case userMessage = "user_message" case count, antani } }
Conclusioni
Questo è giusto un antipasto delle novità introdotte in Swift 4. Spero di avervi stuzzicato l’appetito.
Vi indico un po’ di link per approfondire:
- https://developer.apple.com/videos/play/wwdc2017/212/
- https://developer.apple.com/documentation/swift/codable
- https://developer.apple.com/documentation/swift/codable
Happy coding!
Un commento su “Codable – JSON facile con Swift 4”