15

I am new to swift programming and Xcode and am try to call mysql data from the database to Xcode using Json encoding. I was able to successfully call all the data (array) but when I decide to call only one value(column) say Courses.name I get the "Decoding Error -- Expected to decode Dictionary but found an array instead." How do I work my way around this problem? My goal is to print only courses.name

import UIKit

struct Course: Decodable {
let id: String
let name: String
let member:  String

 }

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    let jsonUrlString = "http://oriri.ng/aapl/service.php"
    guard let url = URL(string: jsonUrlString) else
    { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in

        guard let data =  data else{ return }

        do {

            let courses = try JSONDecoder().decode(Course.self, from: data)
            print(courses.name)


        } catch let jsonErr {
            print("Error serializing json:", jsonErr)
        }

    }.resume()

   }
}
Jamiu Momoh
  • 153
  • 1
  • 1
  • 4

2 Answers2

32

[{"id":"1","name":"sobande_ibukun","member":"blue"}]

The [] around denotes that it is an array. Decode with the following and it should work:

let courses = try JSONDecoder().decode([Course].self, from: data)

If you are sure that it will always be one course you can do:

print(courses.first!.name)

If there may be many courses you can print every name:

courses.forEach { course in print(course.name) }
Fabian
  • 5,040
  • 2
  • 23
  • 35
  • Thank you, but I get another error "Value of type '[Course]' has no member 'name'" and it fails to build – Jamiu Momoh Aug 15 '18 at 21:29
  • @JamiuMomoh Updated the answer to reflect that. An array of courses has elements. You have to access a specific element in the array to call `.name` on it. – Fabian Aug 15 '18 at 21:32
  • Yes! it will always be one course as I will restrict the result with mysql statement. Thank you so much, being trying to wrap my head around it for hours.Works as intended. – Jamiu Momoh Aug 15 '18 at 21:36
  • Not working. get error: error: cannot convert value of type '[Course.Type]' to expected argument type 'T.Type' – ArgaPK Jul 07 '21 at 05:58
  • Thanks, I am very new to Swift and I tried putting the [] in all the wrong places before I got this answer – Sudhir Kesharwani May 02 '23 at 07:12
0

Just wanted to add to Fabians response above.

The fix for showing all of them is to have a struct with each of your keys (in the array) like so:

struct Advisor_Info: Decodable {
    let advisor_email: String
    let advisor_firstname: String
    let advisor_lastname: String
    let advisor_phonenumber: String
}

Then extract your items from the JSON dictionary string like so:

    do {        
        let decodedResponse = try JSONDecoder().decode([Advisor_Info].self, from: data)
        print(decodedResponse as Any)
        for each in decodedResponse {
            print(each)
            print(each.advisor_email)
        }
        
    } catch DecodingError.dataCorrupted(let context) {
        print(context)
    } catch DecodingError.keyNotFound(let key, let context) {
        print("Key '\(key)' not found:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch DecodingError.valueNotFound(let value, let context) {
        print("Value '\(value)' not found:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch DecodingError.typeMismatch(let type, let context) {
        print("Type '\(type)' mismatch:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch {
        print("error: ", error)
    }
}
burnsi
  • 6,194
  • 13
  • 17
  • 27
Run 4ever
  • 31
  • 2