0

So, I have been trying to make this code work for a couple of days and I don't know what I am doing wrong.

I am getting a JSON from the web and parsing it with Struct blocks.

The question is: I want to use the Dictionaries and Array from the JSON out of where I created de decode function.

Here is the code

import UIKit


struct  Currency_format: Decodable{
    var iso_code: String
    var example_format : String
    var decimal_digits : Int
    var decimal_separator : String
    var symbol_first : Bool
    var group_separator : String
    var currency_symbol : String
    var display_symbol : Bool
}

struct  Date_Format: Decodable{
    var format : String
}

struct Budgets: Decodable {
    var id : String
    var name: String
    var last_modified_on : String
    var first_month : String
    var last_month : String
    var date_format : Date_Format
    var currency_format : Currency_format
}

struct DataResponse : Decodable {
    var data : Data
}

struct Data : Decodable{
    var budgets : [Budgets]
}


class ViewController: UIViewController {


override func viewDidLoad() {
    super.viewDidLoad()
    let accessToken = "1234"
    let authorizationRequestHeader = "https://www.somewhere.com=\(accessToken)"


    guard let url = URL(string: authorizationRequestHeader) else {
        print("Error")
        return
    }
    let session = URLSession.shared
    session.dataTask(with: url) { (stringData, response, Error) in
        let testString =  try! dataResponse.decode(DataResponse.self, from:stringData!)
        print("Number of records: \(testString.data.budgets.count)")
        //THIS PRINT WORKS AS I WANT IT TO WORK. NOT PROBLEM HERE
        }.resume()

  print("Number of records: \(testString.data.budgets.count)") // BUT THE SAME CODE HERE, DOES NOT WORK AT ALL
Ratan Uday Kumar
  • 5,738
  • 6
  • 35
  • 54

2 Answers2

0

Do one thing, initialize testString just before the viewDidLoad() Like :

class ViewController: UIViewController {

let testString : DataResponse!

override func viewDidLoad() {
super.viewDidLoad()
    let accessToken = "1234"
    let authorizationRequestHeader = "https://www.somewhere.com=\(accessToken)"


    guard let url = URL(string: authorizationRequestHeader) else {
        print("Error")
        return
    }
    let session = URLSession.shared
    session.dataTask(with: url) { (stringData, response, Error) in
        testString =  try! dataResponse.decode(DataResponse.self, from:stringData!)
        print("Number of records: \(testString.data.budgets.count)")

    }.resume()


print("Number of records: \(testString.data.budgets.count)")
}

Hope this is helpful.

JAINESH DOSHI
  • 250
  • 2
  • 13
  • The last `print` will still fail as it does in the original code. But that is simply because it's being called long before the data is ready. – rmaddy Jul 13 '18 at 15:42
  • Yeah, it worked but I needed to twike a little: self.testString = try! JSONDecoder().decode(DataResponse.self, from:stringData!) – Thiago Gonçalves Pinto Jul 13 '18 at 15:47
  • @ThiagoGonçalvesPinto Because your data is loaded asynchronously in the background via `URLSession`. Meanwhile, the result of the code in `viewDidLoad` keeps going and that last `print` is called long before the data is retrieved from the URL. – rmaddy Jul 13 '18 at 22:44
0

JSON Decoder method does not work normally with snake_case keys available in your JSON. To work as excepted, in this case we have to use CodingKeys methodology.

Refer this documentation for detailed info.

Prasath R
  • 79
  • 3
  • Sample Example: struct Item : Decodable { let title:String,content:String,version:Int,created:Int32,modified:Int32,noteId:Int private enum CodingKeys : String, CodingKey { case title,content,version,created,modified,noteId = "note_id" } } // Inside response completion do { let items = try JSONDecoder().decode([Item].self, from: data) print(items) } catch { print(error) } – Prasath R Jul 13 '18 at 07:16