lightningxcookie
lightningxcookie

Reputation: 81

How to get values nested within dictionary in NSDictionary?

I apologise if the title is unclear. I am not quite sure how exactly NSDictionary and JSON works.

I am trying to make a simple app using Swift that takes values from a .JSON file, and prints them out to the console. Here is my JSON file:

{

"students": [
    {
        "name": "Stew Dent",
        "age": "10",
        "year": 6,
        "grades": [
            {
                "english": "a-plus",
                "math": "b-plus"
            },
            {
                "english": "a",
                "math": "a-minus"
            }
        ]

    },

    {
        "name": "Mary Brown",
        "age": "14",
        "year": 10,
        "grades": [
            {
                "english": "a-plus",
                "math": "a-plus"
            },
            {
                "english": "a-plus",
                "math": "a"
            }
        ]

    }
]

}

Currently, I am able to retrieve the values of everything except the values in "grades". Here is my Swift code:

if let path = Bundle.main.path(forResource: "school", ofType: "json")
    {
        do {
            // Retrieve data from JSON file
            let jsonData = try NSData(contentsOfFile: path, options: .mappedIfSafe)

            // Convert data into NSDictionary
            let jsonResult = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary



            if let students : [NSDictionary] = jsonResult?["students"] as? [NSDictionary]
            {
                if let grades : [NSDictionary] = students["grades"] as? [NSDictionary]
                {
                    for grade: NSDictionary in grades
                    {
                        for (subject, gradevalue) in grade
                        {
                            print ("\(subject): \(gradevalue)")
                        }

                    }
                }



            }



        } catch
        {

        }


    }

If I am not wrong, the "grades" is a dictionary inside the "students" dictionary. However, it fails to run the above code. On the "if let grades..." line, it gives the error message: "Cannot subscript a value of type '[NSDictionary]' with an index type of 'String'.

So what I am I doing wrong? Is there even any way to retrieve those values? Am I missing something? Any help would be greatly appreciated. Thanks :)

Upvotes: 0

Views: 724

Answers (2)

soan saini
soan saini

Reputation: 260

Try this code, this should work looking at what you are trying to do

            if let path = Bundle.main.path(forResource: "student", ofType: "json")
    {
        do {
            // Retrieve data from JSON file
            let jsonData = try NSData(contentsOfFile: path, options: .mappedIfSafe)

            // Convert data into NSDictionary
            let jsonResult = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary



            if let students = jsonResult?["students"] as? [NSDictionary]
            {
                for student in students
                {
                    for grades in student["grades"] as! [[String:String]]{
                        for eachGrade in grades{
                            print("\(eachGrade.key) : \(eachGrade.value)")
                        }

                    }
                }
            }
        }
        catch
        {

        }

}

Upvotes: 0

Leo Dabus
Leo Dabus

Reputation: 236360

You should use Swift native types Data instead of NSData and Dictionary [String:Any] instead of NSDictionary. You also forgot to iterate through each student. Try like this:

do {
    if let dict = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any] {
        print(dict)
        if let students = dict["students"] as? [[String: Any]] {
            print(students)
            for student in students {
                print(student["name"] ?? "")
                if let grades = student["grades"] as?  [[String: Any]] {
                    for grade in grades {
                        for (subject, gradevalue) in grade {
                            print ("student:",student["name"] ?? "", "subject:", subject, "grade:", gradevalue)
                        }
                    }
                }
            }
        }
    }
} catch {
    print(error)
}

Upvotes: 1

Related Questions