0

I am trying to decode JSON. My swift function for decoding the JSON is:

func GetChapInfo(){

    let endpoint = "https://chapel-logs.herokuapp.com/chapel"

    let endpointUrl = URL(string: endpoint)

    do {
        var request = URLRequest(url: endpointUrl!)
        request.httpMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request){
            (data: Data?, response: URLResponse?, error: Error?) in


            let dataAsString = String(data: data!, encoding: .utf8)
            //print(dataAsString)

            if(error != nil) {
                print("Error")
            }
            else{
                do{
                    guard let chapData = try? JSONDecoder().decode(Chapel.self, from: data!) else {
                        print("Error: Couldn't decode data into chapData")
                        return
                    }
                    for E in chapData.chap {
                        print(E.Day as Any)
                    }
                }
        }
        }

        task.resume()
    }
}

my struct in Swift is

struct Chapel: Decodable {
    let chap: [Chap]
}

struct Chap: Decodable {
    let Name: String?
    let Loc: String?
    let Year: Int?
    let Month: Int?
    let Day: Int?
    let Hour: Int?
    let Min: Int?
    let Sec: Int?
}

and my response from the server is:

{"chap":{"Name":"Why Chapel","Loc":"FEC","Year":2018,"Month":9,"Day":4,"Hour":16,"Min":1,"Sec":7}}

However when I run this the program prints out "Error: Couldn't decode data into chapData" and I cannot figure out why.

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
Seth Wheeler
  • 353
  • 1
  • 2
  • 16
  • 1
    Where does `let chap: [Chap]` come from? For this there would be `[ ]` in JSON but isn‘t. Try with `let chap: Chap` – Fabian Sep 04 '18 at 17:10
  • I agree with @Purpose, the issue is that your `chap` field inside `Chapel` is expecting an array of `Chap` objects and your response contains a single one. – nstosic Sep 04 '18 at 17:13
  • @Purpose when I remove the [ ] Xcode gives me the warning Type 'ListViewController.Chap' does not conform to protocol 'Sequence' at the for loop. Also how do you format your code in a comment? – Seth Wheeler Sep 04 '18 at 17:13
  • With the special \` around code. With `let chap: Chap` it would not be a sequence/Array anymore and so not usable this way in a for-loop.You can still print the one with `print(chapData.chap.Day as Any)` though. – Fabian Sep 04 '18 at 17:15
  • @Purpose it worked, thanks. – Seth Wheeler Sep 04 '18 at 17:17

1 Answers1

2

First of all catch decoding errors. Never try?. The caught error is much more descriptive

Expected to decode Array<Any> but found a dictionary instead

Means: The value for key chap is a dictionary, not an array

struct Chapel: Decodable {
    let chap: Chap
}

And then you have to print

print(chapData.chap.Day) 

You can reduce your code. An explicit URLRequest and headers for a default GET request is not needed. This is sufficient:

let endpoint = "https://chapel-logs.herokuapp.com/chapel"
let endpointUrl = URL(string: endpoint)!

do {

    let task = URLSession.shared.dataTask(with: endpointUrl) { (data, response, error) in
    ...
vadian
  • 274,689
  • 30
  • 353
  • 361