Introduction to Path and Query Parameters

Welcome to another lesson in this course. In our previous lessons, we established a foundation by learning about RESTful APIs and making GET requests using Swift's URLSession. Now, we will shift our focus to path and query parameters, essential tools for refining API requests and fetching specific data.

Path and query parameters play a crucial role in making your API requests more precise and efficient. Imagine you are shopping online: selecting a specific item using its ID is akin to a path parameter, while filtering items by categories like price or color resembles query parameters. In this lesson, we'll explore these concepts with practical examples, empowering you to extract just the information you need from an API.

Understanding Path Parameters

Path parameters are part of the URL used to access specific resources within an API, acting as unique identifiers. For example, if you want to retrieve a to-do item with ID 3, the URL would be structured as follows:

Plain text
1http://localhost:8000/todos/3

In this case, 3 is the path parameter specifying the particular item you wish to access.

Fetching Data with Path Parameters

Path parameters allow you to target specific resources within an API, enabling direct access to individual items. In Swift, we use URLSession to send requests. Here's how you can fetch details of a specific to-do item using its ID:

Swift
1import Foundation 2import FoundationNetworking 3 4let dispatchGroup = DispatchGroup() 5dispatchGroup.enter() 6 7let todoId = 3 8let urlString = "http://localhost:8000/todos/\(todoId)" 9 10if let url = URL(string: urlString) { 11 let task = URLSession.shared.dataTask(with: url) { data, response, error in 12 defer { dispatchGroup.leave() } 13 14 if let error = error { 15 print("Error fetching the todo: \(error)") 16 return 17 } 18 19 guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { 20 print("Error fetching the todo with path parameter") 21 if let httpResponse = response as? HTTPURLResponse { 22 print("Status Code: \(httpResponse.statusCode)") 23 } 24 return 25 } 26 27 if let data = data { 28 do { 29 let todo = try JSONDecoder().decode(Todo.self, from: data) 30 print("ID: \(todo.id)") 31 print("Title: \(todo.title)") 32 print("Description: \(todo.description)") 33 print("Done: \(todo.done)") 34 } catch { 35 print("Error decoding JSON: \(error)") 36 } 37 } 38 } 39 task.resume() 40 dispatchGroup.wait() 41} 42 43struct Todo: Codable { 44 let id: Int 45 let title: String 46 let description: String 47 let done: Bool 48}

In this code, the todoId is a path parameter specifying the to-do item with ID 3, forming the URL http://localhost:8000/todos/3. Upon success, you'll see details of the to-do item, illustrating how path parameters enable precise resource access.

Understanding Query Parameters

Query parameters are added to the URL after a ? to filter or modify the data returned by the API. They are formatted as key-value pairs. For instance, if you want to list only the completed to-do tasks, your request would be:

Plain text
1http://localhost:8000/todos?done=true

Here, done=true is the query parameter filtering the results to include only tasks that are marked as completed.

Filtering Data with Query Parameters

Query parameters are attached to the URL to filter or modify the results returned by the API. In Swift, URLComponents is an excellent way to handle query parameters. Let's filter to-do items to list only those marked as done:

Swift
1import Foundation 2import FoundationNetworking 3 4let dispatchGroup = DispatchGroup() 5dispatchGroup.enter() 6 7var urlComponents = URLComponents(string: "http://localhost:8000/todos") 8urlComponents?.queryItems = [ 9 URLQueryItem(name: "done", value: "true") 10] 11 12if let url = urlComponents?.url { 13 let task = URLSession.shared.dataTask(with: url) { data, response, error in 14 defer { dispatchGroup.leave() } 15 16 if let error = error { 17 print("Error fetching todos with query parameter: \(error)") 18 return 19 } 20 21 guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { 22 print("Error fetching todos with query parameter") 23 if let httpResponse = response as? HTTPURLResponse { 24 print("Status Code: \(httpResponse.statusCode)") 25 } 26 return 27 } 28 29 if let data = data { 30 do { 31 let todos = try JSONDecoder().decode([Todo].self, from: data) 32 todos.forEach { todo in 33 print("- \(todo.id): \(todo.title)") 34 } 35 } catch { 36 print("Error decoding JSON: \(error)") 37 } 38 } 39 } 40 task.resume() 41 dispatchGroup.wait() 42}

In this Swift example, we use URLComponents to construct the URL with the query parameter done=true. The full URL looks like http://localhost:8000/todos?done=true, focusing on completed tasks. Success will list done tasks, demonstrating how query parameters streamline specific criteria.

Using Multiple Query Parameters

To refine data retrieval further, you can combine multiple query parameters. For example, you might want to fetch to-do items that are marked as done and have titles starting with a specific prefix.

Here's how you can filter to-do items that are completed and have titles beginning with the prefix "c":

Swift
1import Foundation 2import FoundationNetworking 3 4let dispatchGroup = DispatchGroup() 5dispatchGroup.enter() 6 7var urlComponents = URLComponents(string: "http://localhost:8000/todos") 8urlComponents?.queryItems = [ 9 URLQueryItem(name: "done", value: "true"), 10 URLQueryItem(name: "title", value: "c") 11] 12 13if let url = urlComponents?.url { 14 let task = URLSession.shared.dataTask(with: url) { data, response, error in 15 defer { dispatchGroup.leave() } 16 17 if let error = error { 18 print("Error fetching todos with multiple query parameters: \(error)") 19 return 20 } 21 22 guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { 23 print("Error fetching todos with multiple query parameters") 24 if let httpResponse = response as? HTTPURLResponse { 25 print("Status Code: \(httpResponse.statusCode)") 26 } 27 return 28 } 29 30 if let data = data { 31 do { 32 let todos = try JSONDecoder().decode([Todo].self, from: data) 33 todos.forEach { todo in 34 print("- \(todo.id): \(todo.title)") 35 } 36 } catch { 37 print("Error decoding JSON: \(error)") 38 } 39 } 40 } 41 task.resume() 42 dispatchGroup.wait() 43}

In this example, URLQueryItem is used to combine query parameters done=true and title=c, constructing the URL http://localhost:8000/todos?done=true&title=c. This approach retrieves items satisfying both conditions, highlighting multi-parameter filtering capabilities.

Summary and Preparing for Practice

In this lesson, you’ve learned how to work with both path and query parameters to refine API requests. Path parameters allow you to pinpoint specific resources, whereas query parameters tailor the results based on defined conditions. Together, they provide a robust mechanism for fetching targeted and detailed information from an API.

You are now prepared to tackle the practice exercises, where you will apply these concepts and explore variations to further reinforce your understanding. As you proceed, remember how these skills can be essential for effective API interaction, laying the groundwork for more advanced operations in future lessons. Keep up the momentum as you continue to advance through the course!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal