1

hi I am trying to get more experience in how to fetch JSON code from a website and then parse it. (see code below) this works but I understand from apple this is an "old, 2017" way to do this. And I am having some problems with the dictionary,

Question1. how can I improve the code below without using any other 3rd party methods or software.

how do I get rid of the Optional statements and I just want to print the value of print(jsondata["title"])

I hope you can set me in the right direction.

thx Ron

see code

'''

//: Playground - noun: a place where people can play
// put in some requirements to yse the playground
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

import Foundation
import UIKit

//just a check if I get some output in a variable and to see if the playground is working
var str = "this is a test to see if there is output"

// retrieve the data from a website and put it into an object called jsondata; print the size of jsondata in bytes and put it into a variable called data; put number of elements in jsondata into jsonelements

let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")
URLSession.shared.dataTask(with:url!, completionHandler: {(datasize, response, error) in
    guard let data = datasize, error == nil else { return }

do {
    let jsondata = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]

    //print the dictionary
    print(jsondata)

    // how many elements in the dictionary
    let jsonelements = jsondata.count
    print(jsonelements)

    // Iterate through the dictionary and print the value per key
    for (key,value) in jsondata {
        print("\(key) = \(value)")
    }

    // get the values out of the dictionry
    print(" ")
    print(jsondata["title"])
    print(jsondata["userID"])
    print(jsondata["id"])
    print(jsondata["completed"])

} catch let error as NSError {
    print(error)
}

}).resume()

'''

    // get the values out of the dictionry
    print(" ")
    print(jsondata["title"])
    print(jsondata["userID"])
    print(jsondata["id"])
    print(jsondata["completed"])

here I get a warning "expression implicitly coerced from 'Any?' to Any

why am I getting the warning? and how do I print just print(jsondata["title"] without the warning. I think I am doing it the right way

BhargavR
  • 1,095
  • 7
  • 14
RvE
  • 11
  • 7

3 Answers3

0

To eliminate the warnings and print out the values without the optional do so with if let as the one below.

if let title = jsondata["title"] {
   print(title)
}

You could also do so using guard let

guard let title = jsondata["title"] else { return }
print(title)

If you are 100% of the return type and that it will not be nil use guard let or

print(jsondata["title"] as! String)

However, the example above is not recommended because you generally do not want to force unwrap(!)

As to the warning and another example -> https://stackoverflow.com/a/40691455/9578009

Jesus
  • 36
  • 1
  • 6
0

Standard way of doing it would be to declare a type and use it as below,

// MARK: - Response
struct Response: Codable {
    let userID, id: Int
    let title: String
    let completed: Bool

    enum CodingKeys: String, CodingKey {
        case userID = "userId"
        case id, title, completed
    }
}

URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
    guard let data = data else { return }

    do {
        let response = try JSONDecoder().decode(Response.self, from: data)
        print(response.id)
        print(response.userID)
        print(response.title)
        print(response.completed)
    } catch {
        print(error)
    }

}).resume()
Kamran
  • 14,987
  • 4
  • 33
  • 51
0

Question1. how can I improve the code below without using any other 3rd party methods or software.

Use Decodable, it decodes the data directly into a struct. No optionals, no Any.

//: Playground - noun: a place where people can play
// put in some requirements to yse the playground
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

import Foundation
import UIKit

struct ToDo : Decodable {

    let userId, id : Int
    let title : String
    let completed : Bool
}

let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")!
URLSession.shared.dataTask(with:url) { data, _, error in
    guard let data = data else { print(error!); return }

    do {
        let todo = try JSONDecoder().decode(ToDo.self, from: data)

        // get the values out of the struct
        print(" ")
        print(todo.title)
        print(todo.userId)
        print(todo.id)
        print(todo.completed)

    } catch {
        print(error)
    }
}.resume()
vadian
  • 274,689
  • 30
  • 353
  • 361