Home Swift UNIX C Assembly Go Web MCU Research Non-Tech

How to get get JSON by website api and displays content in SwiftUI

2022-02-11 | Swift | #Words: 1390 | 中文原版

Obtaining JSON from the website API and displaying the text is a very common usage scenario in development.

First, we need to know what the json we want to get looks like. There are two ways to know:

First, query the API documentation: It is generally introduced in the website API documentation, as follows:

JSON format will be introduced in the website API documentation

Second, obtained by using crul -H: This method requires the use of **terminal. The above figure also introduces this method, as follows:

$ curl -H "Accept: application/json" https://icanhazdadjoke.com/
{
   "id": "R7UfaahVfFd",
   "joke": "My dog used to chase people on a bike a lot. It got so bad I had to take his bike away.",
   "status": 200
}

After we know the format of the obtained JSON, we start typing the code. First, we need to add import Combine to the header file. The complete header file is as follows:

import SwiftUI
import Combine

Then, we need to create a new structure to interpret and store the content in JSON format. Taking the example obtained above, each piece of JSON data consists of three elements:

  1. id: It should be noted that id here is a string type. But some id is of UUID type.
  2. joke: Obviously this is a string type.
  3. status: integer type.

Then we write the following structure (Please note that the type must not be written incorrectly, otherwise it will cause decoding errors):

//If the obtained JSON file contains multiple items, we also plan to store them in an array, and Identifiable needs to be added here.
struct Joke: Codable {
     var id: String
     var joke: String
     var status: Int
}

Then we use the newly written Joke type to create a variable to obtain and store the decoded data. The content is all empty or 0 (you can also add appropriate placeholders as needed). And for convenience, I wrote it directly into the view’s structure. **It should be noted that in the demonstration, only one piece of data is obtained each time. We can use a separate variable to store it and refresh it each time. But usually we more often use arrays for storage. If arrays are used for storage here, remember to use append instead of = when assigning values. If the obtained JSON itself contains many pieces of data, then use =. **

@State private var jokes: Joke = Joke(id: "", joke: "", status: 0)

Then we need to write a function to obtain, decode and store JSON data (since we need to use the variables we created above, we need to put this function and variables in the same struct or class), as follows:

func getJoke() {
         //Set the URL to be obtained
         let url = URL(string: "https://icanhazdadjoke.com/")!
         //Request URL
         var urlRequest = URLRequest(url:url)
         //The type requested is application/json (that is, JSON type)
         urlRequest.addValue("application/json",forHTTPHeaderField: "Accept")
         //Check the obtained data
         URLSession.shared.dataTask(with: urlRequest) { data, response, error in
             do {
                 //Assign the data to jokeDate and judge if the data is not empty
                 if let jokeData = data {
                     //Set the decoder to JSONDecoder()
                     let decoder = JSONDecoder()
                     //Decode the obtained data according to the data structure of the Joke structure we created before (if we plan to put it in an array, add square brackets to the Joke here)
                     let decodedData = try decoder.decode(Joke.self, from: jokeData)
                     //In order to prevent too much data and long loading time, asynchronous loading is used here.
                     DispatchQueue.main.async {
                         //Assign the decoded data to the previously prepared empty variable
                         self.jokes = decodedData
                     }
                 } else {
                     //If the data is empty, output the following text on the console
                     print("No data")
                 }
             } catch {
                 print(error)
             }
         }.resume()
     }

The complete code is listed below:

import SwiftUI
import Combine

struct Joke: Codable {
     var id: String
     var joke: String
     var status: Int
}

struct ContentView: View {
     //Variables of Joke data type to obtain and store decoded data
     @State private var jokes: Joke = Joke(id: "", joke: "", status: 0)

     var body: some View {
         VStack {
             Button("get") {
                 getJoke()
             }
             VStack(alignment: .leading) {
                 Text(jokes.joke)
             }
             .onAppear(perform: {
                 //Load data when the interface appears
                 getJoke()
             })
         }
     }
     func getJoke() {
         //Set the URL to be obtained
         let url = URL(string: "https://icanhazdadjoke.com/")!
         //Request URL
         var urlRequest = URLRequest(url:url)
         //The type requested is application/json (that is, JSON type)
         urlRequest.addValue("application/json",forHTTPHeaderField: "Accept")
         //Check the obtained data
         URLSession.shared.dataTask(with: urlRequest) { data, response, error in
             do {
                 //Assign the data to jokeDate and judge if the data is not empty
                 if let jokeData = data {
                     //Set the decoder to JSONDecoder()
                     let decoder = JSONDecoder()
                     //Decode the obtained data according to the data structure of the Joke structure we created before (if we plan to put it in an array, add square brackets to the Joke here)
                     let decodedData = try decoder.decode(Joke.self, from: jokeData)
                     //In order to prevent too much data and long loading time, asynchronous loading is used here.
                     DispatchQueue.main.async {
                         //Assign the decoded data to the previously prepared empty variable
                         self.jokes = decodedData
                     }
                 } else {
                     //If the data is empty, output the following text on the console
                     print("No data")
                 }
             } catch {
                 print(error)
             }
         }.resume()
     }
}

struct ContentView_Previews: PreviewProvider {
     static var previews: some View {
         ContentView()
     }
}

For the convenience of demonstration, they are written together here. Generally, we need to create a new swift file to store the struct, request acquisition and decoding part of the code.

​I hope these will help someone in need~