diegoRodicio

Está documentación está a túa disposición sin ningún custo económico. Sen embargo, para a súa elaboración dedico moito tempo e recursos, polo que agradecería unha colaboración co que consideres oportuno. Gracias.

Cargar un arquivo JSON #

Neste apartado veremos unha forma de cargar un arquivo JSON e traducir as entradas nun array de obxectos.

  • Necesitamos unha clase que teña, como propiedades, as que se correspondan coas claves do arquivo JSON.
  • Unha función que cargue o arquivo JSON nun array de obxectos da clase anterior.

Para explicar o anterior, supoñamos que temos o seguinte arquivo JSON:

[
    {
        "id": "aa32jj887hhg55",
        "nome": "Tesla Model 3",
        "descricion": "Coche totalmente eléctrico de 4 portas. Autonomía 500 km. 0-100 km/h 3.2 segundos.",
        "hibrido": false,
        "nomeImaxe": "tesla_model_3"
    },
    {
        "id": "bb32jj887hhg77",
        "nome": "Tesla Model S",
        "descricion": "Coche eléctrico de 5 portas. O modelo Performance ten varios motores eléctrico que acadan 1020 CV. 0-100 km/h 2.1 segundos.",
        "hibrido": false,
        "nomeImaxe": "tesla_model_s"
    }
]

1 de 3: Creación da clase #

Necesitamos unha clase/estrutura que teña, como propiedades, as que se correspondan coas chaves do arquivo JSON.

  • A estrutura Coche que vamos a crear, ten que implementar os protocolos Codable e Identifiable, para poder cargar o JSON e empregar a vista de List.
  • As propiedades da estrutura que vamos a crear, ten que coincidir exactamente coas claves do arquivo JSON.

Así, supondo o JSON do exemplo, teremos o seguinte código que implementa a clase Coche:

struct Coche: Codable, Identifiable {
    var id: String
    var nome: String
    
    var descricion: String
    var hibrido: Bool
    
    var nomeImaxe: String
}

2 de 3: Cargar JSON #

Empregaremos unha función de que lea un arquivo JSON (pasándolle o nome do arquivo) e devolve un array de obxectos que teña as propiedades que se correspondan coas claves do arquivo JSON.

import Foundation

func cargarJSON(nomeArquivoJSON: String) -> TipoEstrutura {
    let datos: Data
    
    guard let arquivo = Bundle.main.url(forResource: nomeArquivoJSON,
                                  withExtension: nil)
    else {
        fatalError("\(nomeArquivoJSON) non atopado no proxecto.")
    }
    
    do {
        datos = try Data(contentsOf: arquivo)
    } catch {
        fatalError("Non foi posible cargar o arquivo \(nomeArquivoJSON): \(error)")
    }
    
    do {
        return try JSONDecoder().decode(TipoEstrutura.self, from: datos)
    } catch {
        fatalError("Non foi posible parsear o arquivo \(nomeArquivoJSON): \(error)")
    }
}

A función cargarJSON é un exemplo estándar de como cargar un arquivo JSON e pódese utilizar en calquera outro proxecto, é dicir, poderemos empregar esta función para cargar calquera JSON, non so o noso.

  • No noso caso, cando empreguemos a función, devolveranos un array de obxectos Coche.
  • As propiedades dos obxectos Coche son as mesmas que as claves que contén o noso arquivo JSON.

3 de 3: Utilización da clase e da función de carga do arquivo JSON #

Por último, empregamos a función cargarJSOM (Pasándolle o nome do arquivo JSON) e o almacenamos nun array de obxectos.

Así, no exemplo anterior (tendo en conta que o arquivo JSON está almacenado noso proxecto co nome datosCoches.json):

var coches: [Coche]
coches = cargarJSON(nomeArquivoJSON: "datosCoches.json")

Cargar JSON desde unha URL #

A continuación veremos como cargar un arquivo JSON dende unha URL e, posteriormente, tal e como faciamos no punto anterior, transformar o JSON descargado a un modelo da nosa app.

Para iso empregaremos URLSession e JSONDecoder.

Para realizar esta tarefa suporemos un caso real. A través da url https://www.iessanmamede.com/category/novas/feed/json obteremos todas as novas da web do IES San Mamede en formato JSON.

Se descargamos este arquivo no navegador, observamos que o JSON ten o seguinte formato:

{
    "version": "https://jsonfeed.org/version/1.1",
    "user_comment": "This feed allows you to read the posts from this site in any feed reader that supports the JSON Feed format....",
    "next_url": "https://www.iessanmamede.com/category/novas/feed/json?paged=2",
    "home_page_url": "https://www.iessanmamede.com/category/novas",
    "feed_url": "https://www.iessanmamede.com/category/novas/feed/json",
    "language": "gl-ES",
    "title": "Novas arquivos - IES San Mamede",
    "description": "P\u00e1xina Oficial do Instituto de Educaci\u00f3n Secundaria IES San Mamede (Maceda) Ourense",
    "icon": "https://www.iessanmamede.com/wp-content/uploads/2023/08/logo_sm_150.jpg",
    "items": [
        {
            "id": "https://www.iessanmamede.com/?p=2159",
            "url": "https://www.iessanmamede.com/proxecto-emprende-sorteo-ipad/",
            "title": "Proxecto eMprende \u2013 Sorteo iPad",
            "content_html": "Contido da nova en html",
            "date_published": "2024-01-24T16:27:12+01:00",
            "date_modified": "2024-01-24T18:30:40+01:00",
            "authors": [
                {
                    "name": "drodicio",
                    "url": "https://www.iessanmamede.com/author/drodicio/",
                    "avatar": "https://secure.gravatar.com/avatar/e6301037117d1756e160e4853dd3060e?s=512&d=mm&r=g"
                }
            ],
            "author": {
                "name": "drodicio",
                "url": "https://www.iessanmamede.com/author/drodicio/",
                "avatar": "https://secure.gravatar.com/avatar/e6301037117d1756e160e4853dd3060e?s=512&d=mm&r=g"
            },
            "image": "https://www.iessanmamede.com/wp-content/uploads/2024/01/IMG_0403_modificado-scaled.jpg",
            "tags": [
                "Ultimas Novas"
            ],
            "summary": "No marco do proxecto eMprende, a semana pasada tivo lugar o proceso de entrega dun iPad ao alumno agraciado no sorteo, Alejandro Gil..."
        },
        {
            "id": "https://www.iessanmamede.com/?p=1957",
            "url": "https://www.iessanmamede.com/java-magician/",
            "title": "Java Magician",
            "content_html": "Contido da nova en html",
            "date_published": "2023-11-06T12:06:53+01:00",
            "date_modified": "2023-11-06T12:19:45+01:00",
            "authors": [
                {
                    "name": "drodicio",
                    "url": "https://www.iessanmamede.com/author/drodicio/",
                    "avatar": "https://secure.gravatar.com/avatar/e6301037117d1756e160e4853dd3060e?s=512&d=mm&r=g"
                }
            ],
            "author": {
                "name": "drodicio",
                "url": "https://www.iessanmamede.com/author/drodicio/",
                "avatar": "https://secure.gravatar.com/avatar/e6301037117d1756e160e4853dd3060e?s=512&d=mm&r=g"
            },
            "image": "https://www.iessanmamede.com/wp-content/uploads/2023/11/java-scaled.webp",
            "tags": [
                "dam",
                "fp",
                "Inform\u00e1tica",
                "java",
                "programaci\u00f3n"
            ],
            "summary": "En Java Magician podes atopar diversos tutoriais de programaci\u00f3n en Java."
        }
    ]
}

Os datos que nos interesan están dentro da chave items, de xeito que cada elemento de dita chave será unha nova, da que, entre outras, teremos as seguintes chaves:

  • id: O identificador da nova
  • url: A dirección url da nova
  • title: O título da nova
  • image: A dirección url da imaxe de portada da nova
  • summary: O resumo da nova

1 de 4: Creación da estrutura #

Ao igual que fixemos no apartado de cargar un arquivo JSON, necesitamos unha clase/estrutura que teña, como propiedades, as que se correspondan coas chaves do arquivo JSON.

  • A estrutura Nova que vamos a crear, ten que implementar os protocolos Codable e Identifiable, para poder cargar o JSON e empregar a vista de List.
  • As propiedades da estrutura que vamos a crear, ten que coincidir exactamente coas chaves do arquivo JSON.
  • Como vedes na estrutura creada,non é obrigatorio incluír como propiedades todas as chaves do JSON, so as que nos interesan.

Así, supondo o JSON do exemplo, teremos o seguinte código que implementa a estrutura Nova:

  struct Nova: Decodable, Identifiable {
    var id: String
    var url: String
    var title: String
    var summary: String
    let image: String
    
}

2 de 4: Creación do array de Nova #

Como comentamos máis arriba, as novas do IES San Mamede están dentro da chave items do JSON, de xeito que cada elemento de dita chave será unha nova.

O que temos que facer é obter un array de Nova, de xeito que debemos iterar a partir da chave items, para obter todas as novas.

  • Teremos que crear unha enumeración (concretamente no exemplo chámolle CodingKeys) que implemente as clases String e CodingKey que empregamos para indicar cal é a chave do noso arquivo JSON sobre a que iteramos para obter o array de Nova. Como vamos a iterar a partir da chave items, este será un caso da enumeración.
  • No caso de outro arquivo JSON, na enumeración, en lugar de items, poremos o nome da chave sobre a que iteramos
struct NovasResposta: Decodable {
    let novas: [Nova]
    
    enum CodingKeys: String, CodingKey {
        case items
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.novas = try container.decode([Nova].self, forKey: .items)
    }
}

3 de 4: Obter e codificar as novas #

Dentro da clase Novas, imos crear un método chamado getNovas() que o que fará será unha petición HTTP á páxina do IES San Mamede que nos devolve o arquivo JSON coas novas.

Para iso debemos especificar a URL e usar URLSession para realizar a petición HTTP. O código quedaría do seguinte xeito:

final class Novas: ObservableObject {
    
    @Published var novas: [Nova] = []
    let url = URL(string: "https://www.iessanmamede.com/category/novas/feed/json")
    
    func getNovas() {
        URLSession.shared.dataTask(with: url!) { datos, resposta, error in
            if let _ = error {
                print("Error")
            }
            
            if let datos = datos,
               let respostaHTTP = resposta as? HTTPURLResponse,
               respostaHTTP.statusCode == 200 {
                let novas = try! JSONDecoder().decode(NovasResposta.self, from: datos)
                print("Novas \(novas)")
                DispatchQueue.main.async {
                    self.novas = novas.novas
                }
            }
            
        }.resume()
    }
}

Fíxache que se todo vai ben na nosa petición HTTP, empregaremos a propiedade ‌@Published var novas: [Nova] no noso deseño de interfaz mediante SwiftUI. É por iso que necesitamos implementar o protocolo ObservableObject e imos empregar o property wrapper @Published .

Desta maneira, como dixen antes, cada vez que se actualice esta propiedade, a vista que utilizaremos en SwifUI se redebuxará coas novas descargadas.

4 de 4: Implementar a vista en SwifUI #

Agora xa podemos procesar as novas obtidas e almacenadas na clase Novas mediante unha interfaz en SwiftUI.

Velaquí un exemplo:

struct NovasView: View {
    
    @StateObject var novas: Novas = Novas()
    
    var body: some View {
        NavigationView {
            
            
            List(novas.novas) {
                nova in
                Link(destination: URL(string: nova.url)!) {
                    
                    HStack {
                        ImaxeNovaView(url: nova.image)
                        
                        VStack {
                            TituloNovaView(titulo: nova.title)
                            ResumoNovaView(resumo: nova.summary)
                        }
                    }
                }
            }
            .navigationTitle("Novas IES San Mamede")
        }.onAppear {
            novas.getNovas()
        }
    }
}

struct ImaxeNovaView: View {
    var url: String
    
    var body: some View {
        AsyncImage(url: URL(string: url)) { image in
            image
                .resizable()
                .scaledToFit()
                .frame(width: 50)
                .cornerRadius(5)
                .padding()
        } placeholder: {
            ProgressView()
        }
    }
}

struct TituloNovaView: View {
    
    var titulo: String
    
    var body: some View {
        Text(titulo).font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
    }
}

struct ResumoNovaView: View {
    
    var resumo: String
    var body: some View {
        Text(resumo).font(.subheadline)
    }
}

Share Your Valuable Opinions