Issue encountered with a universal utility function designed to extract JSON data from a specified URL

For a project I'm working on, I need to fetch JSON data from multiple URLs in different Views and populate various structs. To achieve this, I've created a compact yet versatile helper function.

This function can be utilized as follows:

View 1:

let call1 = Bundle.main.decode(iobrokerSection.self, from: "http://192.168.1.205:8087/get/javascript.0.Fahrzeiten.Dauer")

View 2:

let call2 = Bundle.main.decodeURL(iobrokerweather.self, from: "http://192.168.1.205:8087/get/javascript.0.Fahrzeiten.Weather")

and so forth.

The struct iobrokerSection for the first example looks like this:

struct iobrokerNumberDataPoint: Codable {
    var val: Int
    var ack: Bool
    var ts: Int
    var q: Int
    var from: String
    var user: String
    var lc: Int
    var _id: String
    var type: String
}

Below is my handy helper function:

extension Bundle {
    func decodeURL<T: Decodable>(_ type: T.Type, from urlString: String) -> T {
        guard let url = URL(string: urlString) else {
            fatalError("Placeholder for a good error message")
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            guard let loaded = try? JSONDecoder().decode(T.self, from: data!) else {
                fatalError("Placeholder for a good error message")
            }
        }.resume()

        return loaded
    }
}

I am encountering a compiler message that says "Cannot convert return expression of type Bool to return Type T" at the line "return loaded" and I'm unsure how to resolve it. Any suggestions would be greatly appreciated!

Answer №1

In Swift, it is recommended to start the names of your structures, classes, and protocols with an uppercase letter. Additionally, you should not wait for asynchronous methods to finish in order to return a value. Instead, you can utilize a completion handler within your method. If your goal is simply to retrieve data without performing any additional actions, there is no need to use URLRequest; you can directly pass a URL to your method. It's important not to force-unwrap the returned data as it could potentially be nil. Always safely unwrap optional data and handle errors by passing them to the completion handler. Your decode method may look something like this:

extension Bundle {
    func decode<T: Decodable>(_ type: T.Type, from url: URL, completion: @escaping (T?, Error?) -> Void) {
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data else {
                completion(nil, error)
                return
            }
            do {
               try completion(JSONDecoder().decode(T.self, from: data), nil)
            } catch {
                completion(nil, error)
            }
        }.resume()
    }
}

When using this method, remember to handle the asynchronous result inside the closure:

struct IOBrokerNumberDataPoint: Codable {
    var val: Int
    var ack: Bool
    var ts: Int
    var q: Int
    var from: String
    var user: String
    var lc: Int
    var id: String
    var type: String
    enum CodingKeys: String, CodingKey {
        case val, ack, ts, q, from, user, lc, id = "_id", type
    }
}

let url = URL(string: "http://192.168.1.205:8087/get/javascript.0.Fahrzeiten.Dauer")!
Bundle.main.decode(IOBrokerNumberDataPoint.self, from: url) { brokerNumberDataPoint, error in
    guard let brokerNumberDataPoint = brokerNumberDataPoint else {
        print("error", error ?? "")
        return
    }
    print("brokerNumberDataPoint", brokerNumberDataPoint)
    // Utilize brokerNumberDataPoint here
}

An alternative approach is to leverage Swift 5 Result generic enumeration.

extension Bundle {
    func decode<T: Decodable>(from url: URL, completion: @escaping (Result<T, Error>) -> Void) {
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else {
                if let error = error { completion(.failure(error)) }
                return
            }
            do {
                try completion(.success(JSONDecoder().decode(T.self, from: data)))
            } catch {
                completion(.failure(error))
            }

        }.resume()
    }
}

Usage:

let url = URL(string: "http://192.168.1.205:8087/get/javascript.0.Fahrzeiten.Dauer")!

Bundle.main.decode(from: url) { (result: Result<IOBrokerNumberDataPoint, Error>) in
    switch result {
    case let .success(brokerNumberDataPoint):
        print("brokerNumberDataPoint", brokerNumberDataPoint)
        // Use brokerNumberDataPoint here
    case let .failure(error):
        print("error:", error)
    }
    
    
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can you use AJAX to retrieve the same URL in both HTTP and HTTPS protocols?

Is it possible to configure AJAX requests to retrieve files based on the protocol being used in the browser? I am aware that AJAX requests cannot be made from HTTP to HTTPS, so we are currently working on making content available through both protocols. F ...

Adjust the contents of a DIV depending on which Toggle button is selected

When a user clicks on either "Twin Bed" or "King Bed", the content inside the "demand-message" should change to either "high demand" or "Only ??? rooms left". The ID will remain the same for both buttons due to existing logic. However, the message display ...

Storing JSON data in a Python variable for future use by applying filters

Is there a way to filter a JSON dataset in Python and store the specified returned object in a variable? Dataset: { id : 121 email : <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="244149454d4815644149454d480 ...

Create a new JSON file to preserve the value of a JSON object

I am working with a JSON file that looks like this: { "soils": [{ "mukey": "658854", "mukeyName": "Meggett-Kenansville-Garcon-Eunola-Blanton-Bigbee (s1517)", "sl_source": "Fl soil map", "cokey": "3035468", "soilName": "Eunola", " ...

Having trouble retrieving data from a local JSON file with Angular

I am attempting to retrieve data from a local JSON file in order to manipulate the data within the view. For example, if you choose UnitOne, the only available 'roles' you can select are 'role1', 'role2', 'role3', et ...

The JavaScript for loop using .appendChild() is inserting the values of the final object, represented as [object object], into the HTML document

$(document).ready(function () { GetDetails(); }); function GetDetails() { let albumlist = document.getElementById("album-list"); $.ajax({ url: '/Store/browseajax', type: 'GET', data: { id: '@ ...

What is the best way to dynamically search and retrieve data from a JSON object in Angular?

I am facing a challenge with my Angular (v. 1.6.3) app where I have fetched a JSON object containing stock price data. The structure of the JSON object only allows querying using brackets, with each key being a string that may include spaces, parentheses, ...

The function echo json_encode($row) is outputting repetitive values

Here is my PHP code: $result = mysql_query("SELECT * FROM backup WHERE owner='$email'") or die(mysql_error()); $dataCount = mysql_num_rows($result); $row = mysql_fetch_array($result); echo json_encode($row); And this is the result it returns: ...

Swift4 JSON Parsing Tool

Looking to convert a JSON file into a Codable struct in Swift4 for iOS11.1 and Xcode9.1, Below is my code: struct Station: Codable { let htmlAttributions: [String] let nextPageToken: String let status: String struct Result: Codable { ...

Retrieving a JavaScript variable's value in Selenium with Python

rwdata = driver.find_elements_by_xpath( "/html/body/div[2]/div/div/div/form[2]/div[2]/table/tbody") This table contains the value of variable r as text/javascript type. for r in rwdata: print(r.text) if r.text != "Booked": ...

"Is there a way to verify the presence of a specific Key-Value pair in a JSONArray

Given a JSONArray, I am looking to check if a particular key value is present in this array. For example, let's consider a specific key value pair like Current Employment Status:False and I want to confirm its existence in the JSONArray provided below ...

Using JSON data to apply text wrapping in a JQGrid column

I need assistance with my JQGrid column which contains a lengthy text string. The issue is that the column width is insufficient to display the entire string in one line. I am utilizing JSON data. Is there a solution to wrap this extended text so it can b ...

Determine the absent information by comparing two JSON objects with JavaScript

Two JSON objects, counties and ctyIndem, are at hand. The counties object contains all the counties in a specific US State, while ctyIndem holds information about indemnities paid in that State by county, excluding those with no payments made. My task is t ...

Incorporate and interpret a custom JSON object within my Shopify Liquid theme

In an attempt to integrate custom data into my Shopify liquid theme, I stored a JSON file in the assets folder. My goal is to retrieve and parse this JSON object within a jQuery method from a JavaScript file also located in the assets folder. Despite try ...

Swagger codegen static documentation with a customized moustache template specifically designed for response messages

I am utilizing swagger-codegen to create static documentation pages. The generated docs are based on Mustache templates that are part of the project. When I run the code with a sample JSON from the Wordnik Swagger API, it creates individual files for eac ...

Dynamically create a button using jQuery and JSON based on specific conditions (either true or false)

Is there a way to generate buttons with specified parameters only if a condition is true? Currently, the buttons are generated without checking conditions. Any help with the correct syntax would be appreciated. Sample JSON code: { "Caption": "Module ...

Importing JSON data into a WPF ListBox

Exploring WPF for the first time and enjoying it, but encountering an issue. I have successfully set up a class to save and load root names and child information in JSON format. I am trying to load the JSON nickname items into a listbox when the program st ...

In Go programming language, modifying the second item in a list will have a direct impact

If you're stuck on what to say, take a closer look at the code and its resulting output. Here's the code snippet: package main import ( "encoding/json" "fmt" ) type Human struct { N string `json:"n"` ...

Convert an array of strings in C# into a JSON array using serialization

In my _Layout.cshtml file, I have the following code. The purpose is to populate some security items in my JavaScript code. LoggedIn and username work fine, but there seems to be an issue with how the roles are being displayed in the JavaScript. The Roles ...

The Json document includes identifiers that start with the dollar sign symbol

I am working with a JSON file that has a structure similar to what you can find here. Within this file, there are keys such as "$schema" and "$ref". Can someone explain the significance of a key name starting with $? ...