Leave a rating/review
Notes: 12. Challenge: Decoding JSON Arrays
This course was originally recorded in April 2020. It has been reviewed and all content and materials updated as of November 2021.
If your type is Encodable, not only can you decode an instance of it in JSON, you can store an array of its instances in JSON.
For this challenge, update your loadJSON() method in ContentView.swift to use the new Tasks.json and PrioritizedTasks.json files in order to load a Task array, and a PrioritizedTask array.
Print out the results to the console in order to see the loaded arrays. Have fun!
The first thing I did was to update the guard statement inside loadJSON to point to the new JSON files to use.
let tasksJSONURL = Bundle.main.url(forResource: "Tasks", withExtension: "json")
let prioritizedTaskJsSONURL = Bundle.main.url(forResource: "PrioritizedTasks", withExtension: "json")
Then, I updated the Data initializers to use the new constant names, as well some of the constant’s names to reflect that multiple tasks and prioritized tasks are being loaded.
let tasksData = try Data(contentsOf: tasksJSONURL)
let tasks = try decoder.decode(Task.self, from: tasksData)
print(tasks)
let prioritizedTasksData = try Data(contentsOf: prioritizedTasksJSONURL)
let prioritizedTasks = try decoder.decode(TaskStore.PrioritizedTasks.self, from: prioritizedTasksData)
print(prioritizedTasks)
Finally, instead of decoding a type of Task or PrioritizedTask, I updated this to reflect that an array of each is being loaded.
let tasks = try decoder.decode([Task].self, from: tasksData)
let prioritizedTasks = try decoder.decode([TaskStore.PrioritizedTasks].self, from: prioritizedTasksData)
Run your app with these changes and check out the console.
There is now a lot more content in the console to reflect the arrays being loaded.
With the challenge completed, how about you start updating the TaskStore to use the prioritized tasks from the JSON file and not hard-code them in the prioritizedTasks property? First, start by removing the onAppear method in the body of ContentView.
Next, select all of your loadJSON’s method code and cut it by hitting Command + X
Cut the loadJSON method.
Content view should now look just as it was before adding your method for loading JSON data. Switch over to the TaskStore.swift file and paste your loadJSON method.
Xcode is showing a bunch of errors about unresolved identifiers. This can be addressed by importing the Foundation framework. So go ahead and add that to the top of the file
import Combine
import Foundation
Exellent, those errors should no be gone. Time to clean up the method a little bit. Start by renaming it to loadJSONPrioritizedTasks to better reflect what you’ll be loading, or decoding.
private func loadJSONPrioritizedTasks
You only need a single URL to load your prioritized tasks, so go ahead and update the guard statement to reflect that.
guard let tasksJSONURL = Bundle.main.url(forResource: "PrioritizedTasks", withExtension: "json") else {
return
}
The decoder constant as well as the catch statement can remain the same, but you can also clean things up a bit within the do block when decoding the JSON array.
let tasksData = try Data(contentsOf: tasksJSONURL)
prioritizedTasks = try decoder.decode([PrioritizedTasks].self, from: tasksData)
Note how, when decoding, you store the array of prioritized tasks in the TaskStore’s prioritizedTasks property. That property, however, has some hard-coded data already. Clean that up so it starts out as an empty array instead.
@Published var prioritizedTasks: [PrioritizedTasks] = []
Whereas before the compiler could infer the type, you now explicitly declare it as an array of PrioritizedTasks. Build and run the app.
It’s empty, why is that? the loadJSONPrioritizedTasks method is not getting called anywhere. A great place to do this is in an initializer for TaskStore.
init() {
loadJSONPrioritizedTasks()
}
Now run your app again and check out the results. Excellent, your app no longer uses hard-coded data in your code, but instead is loading it from a file in your app’s bundle.