Categorie
Blog iOS macOS Programmazione Swift

Codable – JSON facile con Swift 4


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:

Happy coding!

1 risposta su “Codable – JSON facile con Swift 4”

[…] Un concetto fondamentale è l’esistenza delle risorse a cui si può accedere tramite un identificatore globale (URI: Uniform Resource Interface). Il client deve solo sapere qual è l’URI per accedere alla risorsa, gli eventuali parametri (ID della risorsa ad esempio) e il formato di rappresentazione che generalmente (e in questo articolo) è il JSON (guarda come è semplice lavorare in JSON con Swift 4). […]

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *