Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter API Response to include/exclude some data from TableView in Swift

Tags:

json

swift

I'm trying to exclude some data I'm receiving from API response,

API Response:

{"status":"ok","answer":[{
                    address = Newyork;
                    comments = test;
                    "contact_name" = "[email protected]";
                    status = "4";
                    },
                    {
                    address = Ohio;
                    comments = test;
                    "contact_name" = "[email protected]";
                    "status" = "3";
                    },
                    {
                    address = cityname;
                    comments = test;
                    "contact_name" = "[email protected]";
                    status = "3";
                    },
                    {
                    address = Washington;
                    comments = test;
                    "contact_name" = "[email protected]";
                    status = "4";
      }
      )
      )

What I'm trying to achieve is, to filter this response, and view only the orders that have status "4" in TableView.

Here is what I tried so far:

func getOrdersHistory() {

    DispatchQueue.main.async {

        let headers = [
            "content-type" : "application/x-www-form-urlencoded",
            "cache-control": "no-cache",
            "postman-token": "dded3e97-77a5-5632-93b7-dec77d26ba99"
        ]

        let user  = CoreDataFetcher().returnUser()
        let email = user.email!

        let postData = NSMutableData(data: "data={\"email\":\"\(email)\",\"type_id\":\"2\"}".data(using: String.Encoding.utf8)!)
        let request = NSMutableURLRequest(url: NSURL(string: "http://www.someApi/Orders")! as URL,
                                          cachePolicy: .useProtocolCachePolicy,
                                          timeoutInterval: 10.0)

        request.httpMethod          = "POST"
        request.allHTTPHeaderFields = headers
        request.httpBody            = postData as Data

        let session  = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
            if (error != nil) {
                print(error!)
            } else {
                if let dataNew = data, let responseString = String(data: dataNew, encoding: .utf8) {
                    print(responseString)


                    let dict = self.convertToDictionary(text: responseString)
                    print(dict?["answer"] as Any)
                    self.responseArray = (dict?["answer"] as! NSArray) as! [ConfirmedOrders.JSONDictionary]
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }


                }

            }

        })

        dataTask.resume()
    }
}

func convertToDictionary(text: String) -> [String: Any]? {
    if let data = text.data(using: .utf8) {
        do {
            return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]

        } catch {
            print(error.localizedDescription)
        }
    }
    return nil
}

This way, I'm getting in TableView, regardless of their status, Can anyone help please?

like image 298
Jessica Kimble Avatar asked Dec 30 '25 18:12

Jessica Kimble


2 Answers

Based on your dataset and using pure Swift arrays and dictionaries, you can simply filter like so:

func getConfirmedOrders(in dict: [String:Any]) -> [[String:Any]] {
    guard
        let answers = dict["answer"] as? [[String:Any]]
        else { print("Answer key not present"); return [] }
    
    //Your basic filter operation
    let filtered = answers.filter { (answer) -> Bool in
        return answer["status"] as? String == "4"
    }
    
    return filtered
}

It's just about proper type casting and then applying the filter operation on it.

Simply using it like so:

self.responseArray = self.getConfirmedOrders(in: dict)
DispatchQueue.main.async {
    self.tableView.reloadData()
}

However, I see that your responseArray is of type [ConfirmedOrders.JSONDictionary].
So either change getConfirmedOrders(from:) to return [ConfirmedOrders.JSONDictionary] or change your responseArray to be of type [[String:Any]].


Playground Example

let jsonString = """
{"status":"ok","answer":[{"address":"Newyork","comments":"test","contact_name":"[email protected]","status":"4"},{"address":"Ohio","comments":"test","contact_name":"[email protected]","status":"3"},{"address":"cityname","comments":"test","contact_name":"[email protected]","status":"3"},{"address":"Washington","comments":"test","contact_name":"[email protected]","status":"4"}]}
"""

if let data = jsonString.data(using: .utf8) {
    do {
        //basically what you have in `convertToDictionary(text:)`
        let dict = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]

        let filtered = getConfirmedOrders(in: dict)
        print(filtered)
    }
    catch {
        print(error)
    }
}

Suggestions:

  1. Use Codable models instead of Swift array and dictionary
  2. Use Swift Array instead of NSArray, and similarly use Swift Dictionary instead of NSDictionary
like image 70
staticVoidMan Avatar answered Jan 01 '26 06:01

staticVoidMan


You need

do {

    let dec = JSONDecoder()
    dec.keyDecodingStrategy = .convertFromSnakeCase
    let res = try dec.decode(Root.self, from: data)
     // here filter like e.x
     let filtered = res.answer.filter { $0.status == "4" }
}
catch{
    print(error)
}

struct Root: Codable {
    let status: String
    let answer: [Answer]
}

struct Answer: Codable {
    let address, comments, contactName, status: String
}

If you need to git rid of Root then do

do {

    guard let data = data else { return }
    let dic = try JSONSerialization.jsonObject(with:data, options: []) as! [String:Any]
    let dataAns = try JSONSerialization.data(withJSONObject:dic["answer"]!, options: [])

    let dec = JSONDecoder()
    dec.keyDecodingStrategy = .convertFromSnakeCase
    let res = try dec.decode([Answer].self, from: dataAns)
     // here filter like e.x
     let filtered = res.filter { $0.status == "4" }
}
catch{
    print(error)
}
like image 34
Sh_Khan Avatar answered Jan 01 '26 08:01

Sh_Khan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!