1

Perhaps it is staring me right in the face, but I keep running into problems when I try to fill a Swift Dictionary to get rendered for a Kitura/Stencil webpage.

In short, I'm calling a local server with an HTTP request (REST API) that sends back a JSON and I'm trying to copy that over into a dictionary that I'm rendering with Stencil.

New to Swift, I'm trying to get my head around how to construct this. I've tried a dozen examples but whenever I'm copying the returned JSON in the dictionary context which I feed into the render method of the response, it seems empty.

The code snippet is:

  router.get("/") {
  request, response, next in
  defer { next() }

  let todoEndpoint = "http://localhost:8090/"

  var context = [String: Any]()
  guard let url = URL(string: todoEndpoint) else { return }

  URLSession.shared.dataTask(with: url) { (data, response, error)
    in
    // perhaps err handling & response checking should be added
    guard let data = data else { return  }
    do {
     let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
      print ("\n json is \(json)")

      let info = json["Result1"] as! [Any]
      //  print ("info is \(info)")
        context["results"] = info
        print ("\n context in the info = json - section: \(context)")

    } catch let jsonErr { print ("Json error occurred")}

  }.resume()
  print ("\n context just before the response: \(context)")
  try response.render("home", context: context)
}

the print statements are - in order of appearance in my Linux terminal:

context just before the response: [:]

json is

[
  "Result1": [
    [
      "stockNumber": "1",
      "instock": "45",
      "description": "survival tent",
      "price": "250.0",
      "replenVal": "15"
    ],
    [
      "stockNumber": "2",
      "instock": "35",
      "description": "hiking shoes",
      "price": "150.0",
      "replenVal": "20"
    ],
    [
      "stockNumber": "3",
      "instock": "67",
      "description": "flash light P12",
      "price": "15.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "4",
      "instock": "34",
      "description": "flash light P15",
      "price": "12.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "5",
      "instock": "50",
      "description": "flash light P18",
      "price": "82.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "6",
      "instock": "50",
      "description": "light weight tent",
      "price": "124.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "7",
      "instock": "5",
      "description": "sleeping bag polar",
      "price": "349.0",
      "replenVal": "5"
    ],
    [
      "stockNumber": "8",
      "instock": "25",
      "description": "sleeping bag eco",
      "price": "149.0",
      "replenVal": "5"
    ],
    [
      "stockNumber": "9",
      "instock": "85",
      "description": "sleeping bag XL",
      "price": "249.0",
      "replenVal": "25"
    ],
    [
      "stockNumber": "10",
      "instock": "126",
      "description": "thermo mug",
      "price": "9.0",
      "replenVal": "50"
    ]
  ]
]

context in the info = json - section:

[
  "results": [
    [
      "stockNumber": "1",
      "instock": "45",
      "description": "survival tent",
      "price": "250.0",
      "replenVal": "15"
    ],
    [
      "stockNumber": "2",
      "instock": "35",
      "description": "hiking shoes",
      "price": "150.0",
      "replenVal": "20"
    ],
    [
      "stockNumber": "3",
      "instock": "67",
      "description": "flash light P12",
      "price": "15.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "4",
      "instock": "34",
      "description": "flash light P15",
      "price": "12.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "5",
      "instock": "50",
      "description": "flash light P18",
      "price": "82.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "6",
      "instock": "50",
      "description": "light weight tent",
      "price": "124.0",
      "replenVal": "50"
    ],
    [
      "stockNumber": "7",
      "instock": "5",
      "description": "sleeping bag polar",
      "price": "349.0",
      "replenVal": "5"
    ],
    [
      "stockNumber": "8",
      "instock": "25",
      "description": "sleeping bag eco",
      "price": "149.0",
      "replenVal": "5"
    ],
    [
      "stockNumber": "9",
      "instock": "85",
      "description": "sleeping bag XL",
      "price": "249.0",
      "replenVal": "25"
    ],
    [
      "stockNumber": "10",
      "instock": "126",
      "description": "thermo mug",
      "price": "9.0",
      "replenVal": "50"
    ]
  ]
]

I've checked the JSON coming from the back-end server for being valid, and it is. I don't see why:

  • The printout starts with the empty context Dictionary, while I expect it to be last
  • Why the context Dictionary is filled when in the do-catch while empty outside the do-catch
  • Any ideas how to gt this working?

Many thanks

L_J
  • 2,351
  • 10
  • 23
  • 28
thewall
  • 53
  • 6
  • A common misunderstanding: `dataTask` works asynchronously. First the code after `.resume` is executed then later the closure. And don't print a useless literal string in a `catch` block, print the `error` – vadian Jul 29 '18 at 18:56
  • Hi vadian. Right, OK Thanks. Still, I'm struggling to get this to work. I've moved the "try response.render("home", context: context)" before the .resume but that gives a compile error with the for me meaningless message: "invalid conversion from throwing function of type '(_, _, _) throws -> ()' to non-throwing function type '(Data?, URLResponse?, Error?) -> Void' URLSession.shared.dataTask(with: url) { (data, response, error)" So How do I get the context dictionary passed into the render part (btw, the printing is done to give me/you some clues of what happens...) – thewall Jul 29 '18 at 19:47
  • You have to move the render line at the end of the `do` block **inside** the closure. – vadian Jul 29 '18 at 19:49
  • Argh, Yep, I was given an compile error... but at a closer look I saw it was about my two separate 'response's (the one from the get call and the URLSession one. Thanks, the rendering is not yet there, but at least I see it running. many thanks! – thewall Jul 29 '18 at 20:14

0 Answers0