How to turn a dictionary json file into an array json file?

how to turn a dictionary json file into an array json file?

The M4 challenge has a json file that contains a dictionary instead of an array.

Thanks

Hey, you have to make a structure (struct) for the JSON.

Its pretty straightforward unless you’re dealing with arrays as one of the key’s value.

Like if your JSON had two keys that were both strings, you would make a struct with two properties that are both strings (with the property names matching the keys of the JSON).

@gotgoodjob
The Guidebook App you created in that course also has a json file. Lesson 9 talks about json code and Lesson 10 covers how to parse it.

but that json file contains a array, not a dictionary.

This is the JSON File
{
  "companies": [
    {
      "company_name": "ABC Corporation",
      "departments": [
        {
          "department_name": "HR",
          "employees": [
            {
              "name": "John Smith",
              "position": "HR Manager",
              "email": "john.smith@abccorp.com",
              "phone": "+1 (123) 456-7890"
            },
            {
              "name": "Emily Davis",
              "position": "HR Specialist",
              "email": "emily.davis@abccorp.com",
              "phone": "+1 (234) 567-8901"
            },
            {
              "name": "Michael Johnson",
              "position": "HR Coordinator",
              "email": "michael.johnson@abccorp.com",
              "phone": "+1 (345) 678-9012"
            },
            {
              "name": "Sarah Brown",
              "position": "HR Assistant",
              "email": "sarah.brown@abccorp.com",
              "phone": "+1 (456) 789-0123"
            }
          ]
        },
        {
          "department_name": "Finance",
          "employees": [
            {
              "name": "David Wilson",
              "position": "Finance Manager",
              "email": "david.wilson@abccorp.com",
              "phone": "+1 (567) 890-1234"
            },
            {
              "name": "Jennifer Lee",
              "position": "Financial Analyst",
              "email": "jennifer.lee@abccorp.com",
              "phone": "+1 (678) 901-2345"
            },
            {
              "name": "Robert Turner",
              "position": "Accountant",
              "email": "robert.turner@abccorp.com",
              "phone": "+1 (789) 012-3456"
            },
            {
              "name": "Laura Martinez",
              "position": "Finance Assistant",
              "email": "laura.martinez@abccorp.com",
              "phone": "+1 (890) 123-4567"
            }
          ]
        },
        {
          "department_name": "Marketing",
          "employees": [
            {
              "name": "Jessica White",
              "position": "Marketing Director",
              "email": "jessica.white@abccorp.com",
              "phone": "+1 (987) 654-3210"
            },
            {
              "name": "Kevin Adams",
              "position": "Marketing Manager",
              "email": "kevin.adams@abccorp.com",
              "phone": "+1 (876) 543-2109"
            },
            {
              "name": "Megan Hall",
              "position": "Marketing Specialist",
              "email": "megan.hall@abccorp.com",
              "phone": "+1 (765) 432-1098"
            },
            {
              "name": "Daniel Garcia",
              "position": "Marketing Coordinator",
              "email": "daniel.garcia@abccorp.com",
              "phone": "+1 (654) 321-0987"
            }
          ]
        },
        {
          "department_name": "IT",
          "employees": [
            {
              "name": "Andrew Clark",
              "position": "IT Director",
              "email": "andrew.clark@abccorp.com",
              "phone": "+1 (543) 210-9876"
            },
            {
              "name": "Michelle Baker",
              "position": "IT Manager",
              "email": "michelle.baker@abccorp.com",
              "phone": "+1 (432) 109-8765"
            },
            {
              "name": "William Taylor",
              "position": "Systems Administrator",
              "email": "william.taylor@abccorp.com",
              "phone": "+1 (321) 098-7654"
            },
            {
              "name": "Samantha Wright",
              "position": "IT Specialist",
              "email": "samantha.wright@abccorp.com",
              "phone": "+1 (210) 987-6543"
            }
          ]
        }
      ]
    },
    {
      "company_name": "XYZ Inc.",
      "departments": [
        {
          "department_name": "Sales",
          "employees": [
            {
              "name": "Christopher Johnson",
              "position": "Sales Director",
              "email": "christopher.johnson@xyzinc.com",
              "phone": "+1 (555) 123-4567"
            },
            {
              "name": "Amanda Smith",
              "position": "Sales Manager",
              "email": "amanda.smith@xyzinc.com",
              "phone": "+1 (555) 234-5678"
            },
            {
              "name": "Matthew Davis",
              "position": "Sales Representative",
              "email": "matthew.davis@xyzinc.com",
              "phone": "+1 (555) 345-6789"
            },
            {
              "name": "Olivia Wilson",
              "position": "Sales Associate",
              "email": "olivia.wilson@xyzinc.com",
              "phone": "+1 (555) 456-7890"
            }
          ]
        },
        {
          "department_name": "Engineering",
          "employees": [
            {
              "name": "Ryan Martinez",
              "position": "Chief Engineer",
              "email": "ryan.martinez@xyzinc.com",
              "phone": "+1 (555) 567-8901"
            },
            {
              "name": "Sophia Lee",
              "position": "Software Engineer",
              "email": "sophia.lee@xyzinc.com",
              "phone": "+1 (555) 678-9012"
            },
            {
              "name": "Ethan Brown",
              "position": "Hardware Engineer",
              "email": "ethan.brown@xyzinc.com",
              "phone": "+1 (555) 789-0123"
            },
            {
              "name": "Isabella Taylor",
              "position": "QA Engineer",
              "email": "isabella.taylor@xyzinc.com",
              "phone": "+1 (555) 890-1234"
            }
          ]
        },
        {
          "department_name": "Customer Support",
          "employees": [
            {
              "name": "James Adams",
              "position": "Customer Support Manager",
              "email": "james.adams@xyzinc.com",
              "phone": "+1 (555) 901-2345"
            },
            {
              "name": "Lily Turner",
              "position": "Support Specialist",
              "email": "lily.turner@xyzinc.com",
              "phone": "+1 (555) 012-3456"
            },
            {
              "name": "Daniel Hall",
              "position": "Support Representative",
              "email": "daniel.hall@xyzinc.com",
              "phone": "+1 (555) 123-4567"
            },
            {
              "name": "Chloe Garcia",
              "position": "Support Associate",
              "email": "chloe.garcia@xyzinc.com",
              "phone": "+1 (555) 234-5678"
            }
          ]
        },
        {
          "department_name": "Research and Development",
          "employees": [
            {
              "name": "William Clark",
              "position": "Research Director",
              "email": "william.clark@xyzinc.com",
              "phone": "+1 (555) 345-6789"
            },
            {
              "name": "Emma Baker",
              "position": "Research Scientist",
              "email": "emma.baker@xyzinc.com",
              "phone": "+1 (555) 456-7890"
            },
            {
              "name": "Aiden Wright",
              "position": "Development Engineer",
              "email": "aiden.wright@xyzinc.com",
              "phone": "+1 (555) 567-8901"
            },
            {
              "name": "Grace Martinez",
              "position": "Product Designer",
              "email": "grace.martinez@xyzinc.com",
              "phone": "+1 (555) 678-9012"
            }
          ]
        }
      ]
    }
  ]
}

There are the structs
struct Company: Identifiable, Codable {
    
    let id = UUID()
    var company_name: String
    var departments: [Department]
    
}

struct Department: Identifiable, Codable {
    
    let id = UUID()
    var department_name: String
    var employees: [Employee]
    
}

struct Employee: Identifiable, Codable {
    

    let id = UUID()
    var name: String
    var position: String
    var email: String
    var phone: String
    
}

This is the code to parse the json file

class DataService {
    
    func getFileData()->[Company] {
        
        //Get the url of the data file
        if let url = Bundle.main.url(forResource: "PhoneBook", withExtension: "json") {
            
            do {
                
                let data = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                
                do {
                    
                    let companies = try decoder.decode([Company].self, from: data)
         
                    return companies
                    
                } catch {
                    print("Fail to decode the data: \(error)")
                }
                
                
            } catch {
                
                print("Can not get any data from the file: \(error)")
                
            }
            
        }
        return [Company]()
    }
}





Problem solved.

//
//  DataService.swift
//  PhoneBook
//
//  Created by Carlos Dos santos on 25/11/2023.
//

import Foundation

class DataService {
    
    var companies = [Company]()
    
    func getFileData() -> [Company] {
        
        // Get the URL of the data file
        if let url = Bundle.main.url(forResource: "PhoneBook", withExtension: "json") {
            
            do {
                let data = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                
                do {
                    let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
                    
                    if let jsonDictionary = jsonObject as? [String: Any] {
                        // Decode the company data from the JSON dictionary
                        if let companyData = jsonDictionary["companies"] as? [[String: Any]] {
                            companies = try decoder.decode([Company].self, from: JSONSerialization.data(withJSONObject: companyData, options: []))
                        }
                    }
                } catch {
                    print("Failed to decode the data: \(error)")
                }
                
            } catch {
                print("Can not get any data from the file: \(error)")
            }
            
        }
        
        return companies
    }
}

1 Like

The solution you have is one way around it but you could have done this:

Data Models:

struct DataResponse: Codable {
    var companies: [Company]
}

// MARK: - Company
struct Company: Identifiable, Codable {
    var id = UUID()
    var companyName: String
    var departments: [Department]

    enum CodingKeys: String, CodingKey {
        case companyName = "company_name"
        case departments
    }
}

// MARK: - Department
struct Department: Identifiable, Codable {
    var id = UUID()
    var departmentName: String
    var employees: [Employee]

    enum CodingKeys: String, CodingKey {
        case departmentName = "department_name"
        case employees
    }
}

// MARK: - Employee
struct Employee: Identifiable, Codable {
    var id = UUID()
    var name: String
    var position: String
    var email: String
    var phone: String

    enum CodingKeys: String, CodingKey {
        case name, position, email, phone
    }
}

A very very useful on-line tool to derive the data model for json is this one: https://app.quicktype.io
Paste the json code in the left panel and it will give you a data model struct on the right.

The only thing it did not do was add the CodingKeys for the Employee struct.

Your original decoding function was on the right track except that you needed to add that one struct above Company.

DataService

class DataService {
    
    func getFileData()->[Company] {
        
        //Get the url of the data file
        if let url = Bundle.main.url(forResource: "PhoneBook", withExtension: "json") {
            
            do {
                
                let data = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                
                do {
                    
                    let decodedJson = try decoder.decode(DataResponse.self, from: data)
         
                    return decodedJson.companies
                    
                } catch {
                    print("Fail to decode the data: \(error)")
                }
                
                
            } catch {
                
                print("Can not get any data from the file: \(error)")
                
            }
            
        }
        return [Company]()
    }
}

Then the courss has not given us enough information. Remember, we are just the beginners for this material. I am aware the we need to use Google when we work as a developer. But at this early stage, it is very discouraging. We should at least be given some hints for this challenge.

That’s a fair comment. I’ll provide some feedback to the team to see if there is some hints that can be added to the challenge description.

Don’t be discouraged. Part of the learning process is to be presented with challenges to push you outside of your comfort zone. That will accelerate your learning and reinforce what you have learned at the same time.

For completing this project, do I need to add info.plist to Xcode 15? How? Thanks.

The info.plist file is no longer a separate entity in the project Bundle. It is part of the root level of the project in the Navigator panel on the left as indicated in this screenshot.

You only add entries in the property list when they are needed.

Do I need to do anything with that section? Anyway, I have just completed the project.

Not for this project. Chris Ching covers that aspect in each course where there is a need to add an entry.