3

So I am making an HTTP request and I get a response that looks like this:

{
  "code": 200,
  "status": "success",
  "patients": {
    "bogdanp": {
      "_id": "5e77c7bbc7cbd30024f3eadb",
      "name": "Bogdan Patient",
      "phone": "0732958473"
    },
    "robertp": {
      "_id": "5e77c982a2736a0024e895fa",
      "name": "Robert Patient",
      "phone": "0739284756"
    }
  }
}

How to get "bogdanp" as a string, and how do I access the object properties? For example, how to access "name" or "phone" etc.?

Here is my HTTP code:

func getPatients(link: String, username: String)
{
    var code = 0 // this is the variable that stores the error code from the response, it is initially set to 0
    let parameters: [String : Any] = ["username": username]
    let url = URL(string: link)!
    let session = URLSession.shared
    var request = URLRequest(url: url)

    request.httpMethod = "POST"
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
    } catch _ {
        }

        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            guard error == nil else {
                return
            }
            guard let data = data else {
                return
            }
            do {
                if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                        // Here I want to access the json response
                    }
            } catch _ {
            }
        })
    task.resume()
}
Roland Lariotte
  • 2,606
  • 1
  • 16
  • 40
Susca Bogdan
  • 991
  • 1
  • 9
  • 23

1 Answers1

3

The best way to make a call request with SwiftUI is to use Combine.

You will first have to create a Model of your JSON object that you want to get back:

import Foundation

//MARK: - Your object to retrieve from JSON
struct Doctor: Codable, Identifiable {
  let id = UUID()
  let patients: [Patients]
}

struct Patients: Codable {
  let id: String
  let name: String
  let phone: String
}

You then create a class that will handle your JSON requests using Combine (I added a plus for you to handle any response error):

import Foundation
import Combine

class Network {

  // Handle your request errors
  enum Error: LocalizedError {
    case invalidResponse
    case addressUnreachable(URL)

    var errorDescription: String? {
      switch self {
      case .invalidResponse:
        return "The server responded with garbage."
      case .addressUnreachable(let url):
        return "\(url.absoluteString) is unreachable."
      }
    }
  }

  // Add your url
  let urlRequest = URL(string: "your url")!

  // Networking on concurrent queue
  let networkQueue = DispatchQueue(label: "Networking",
                                   qos: .default,
                                   attributes: .concurrent)

  // Combine network call (This replace your previous code)
  func downloadPatients() -> AnyPublisher<Doctor, Error> {
    URLSession.shared
      .dataTaskPublisher(for: urlRequest)
      .receive(on: networkQueue)
      .map(\.data)
      .decode(type: Doctor.self, decoder: JSONDecoder())
      .mapError { (error) -> Network.Error in
        switch error {
        case is URLError:
          return Error.addressUnreachable(self.urlRequest)
        default:
          return Error.invalidResponse
        }
    }
    .eraseToAnyPublisher()
  }
}

And now, in your SwiftUI file, where you need this values, you just need to call the downloadPatients() function and use the return data as you wish:

import SwiftUI

let networkRequest = Network()

//MARK: - Call this function where you want to make your call
func loadPatients() {
  _ = networkRequest.downloadPatients()
    .sink(
      receiveCompletion: {
        print("Received Completion: \($0)") },
      receiveValue: { doctor in
        // doctor is your response and [0].name is your first patient name
        print(doctor.patients[0].name) }
  )
}
Roland Lariotte
  • 2,606
  • 1
  • 16
  • 40
  • hello @Roland i use your answer but have a query – Shubhank Gupta Feb 04 '21 at 08:30
  • What kind of query do you have? Bearer? Content-Type? Authentification? Can you post a question on StackOverflow with your URLRequest specificity and add the link on the conversation? – Roland Lariotte Feb 04 '21 at 09:39
  • hey thanks @Roland for reply i post my question here can you plz help https://stackoverflow.com/questions/66043573/unable-to-get-the-response-from-url-using-combine-with-swiftui – Shubhank Gupta Feb 04 '21 at 10:17