Learn Courses My Dashboard

Displaying JSON data

Hey Chris, I have an urgent time sensitive hump I’m trying to get over. I am trying to display data from my WIX account using JSON. I have an api link and I was able to get it to print in to the output in XCODE but with every tutorial I have seen and used I just can’t get it to display. It’s simple because I just need a jumping off point. Below is the URL. Please help:

https://www.goedash.com/_functions/api/DummyData

@coder3000

Your json code is invalid.

This is a very useful site for validating json: https://jsonlint.com

Oh! So do I just past the link the the field to have it tell me if it is valid?

This is the code that I am using that give me access to the data the end point above. Could there be something wrong with this code:

// Type in the Data Collection names you do allow to be a part
// of the common API functions
let whiteList = “DummyData, SampleData”;

export function get_api(request) {
const response = {
“headers”: {
“Content-Type”: “application/json”
}
};

// Get name of Data Collection from path[0]
let datacollection = request.path[0]; // "DummyData"

if (whiteList.includes(datacollection)) {
	return wixData.query(datacollection)
	.limit(100)
	.find()
	.then((apiResults) => {
		if (apiResults.totalCount > 0) {
			response.body = {
				"items": JSON.stringify(apiResults.items)
			};
			return ok(response);
		}
		response.body = {
			"items": "No items found in the collection."
		};
		return ok(response);
	})
}
response.body = {
	"error": "Data Collection is not allowed to be used through this API."
};
return badRequest(response);

}

When I passed this I got a “Valid JSON”

{“items”:"[{“name”:“My name is Gilbert”,“greetings”:“Hello world”,"_id":“7ad33209-1223-449b-afbc-c69d20935389”,"_owner":“04c4cdf4-723c-4c3b-a14d-6867c733b2d1”,"_createdDate":“2022-06-26T17:05:18.192Z”,"_updatedDate":“2022-06-27T20:13:13.707Z”,“title”:“User”}]"}

The link gave me a “Unable to connect”:

https://www.goedash.com/_functions/api/DummyData

This is my Swift code:

import UIKit

class ViewController: UIViewController {

@IBOutlet var greetingsLbl: UILabel!
@IBOutlet var nameLbl: UILabel!


let urlString = "https://www.goedash.com/_functions/api/DummyData"

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    fetchData()
    
    
}

func fetchData() {
    
    let url = URL(string: urlString)
    let defaultSession = URLSession(configuration: .default)
    let dataTask = defaultSession.dataTask(with: url!) {
        (data: Data?, response: URLResponse?, error: Error?) in
        
        if( error != nil ) {
            
            print(error!.localizedDescription)
            return
            
        }
        
        do {
            
            let json = try JSONDecoder().decode(Intro.self, from: data!)
                
                DispatchQueue.main.async {
                    self.greetingsLbl.text = json.greetings
                    self.nameLbl.text = json.name
                }
           
        }
        
        catch {
            
            print(error.localizedDescription)
            return
            
            
        }
        
    }
    dataTask.resume()
    return
    
}



struct Intro: Codable {
    
    let greetings: String
    let name: String

    
}

}

Whatever that code is that you are using to generate your json is not working properly since pasting that generated json code into jsonlint.com says that it is not valid. That’s why your Swift decoder is complaining.

In your catch clause add the following line of code to get more information in your Console messages on what the decoder is not happy with.

print(error.localizedDescription)

(edit)
When you paste that json into the validator you must tap on the button down the bottom labeled “Validate Json”.

Errors will be indicated in the Results block below that button.

This is what I got. Which is weird.

What is also strange is that jsonlint.com says it’s valid on my end.

also that was without the question marks.

With the question marks…

I got this:

So I toggle “Connect Hardware keyboard” off…

and I keep the question marks in…

now I got no errors but nothing in the view. The idea is to display JSON data.

When I take out the question marks I still get this:

Putting question marks against the properties in the struct just says that the data may or may not be there which means that it is Optional.

Your struct does not match your json output either since you are passing an array of “items” with properties of:
name
greeting
_id
_owner
_createdDate
_updatedDate
title

Those need to be specified in your struct somehow depending on what you are ultimately trying to achieve.

What I want to achieve is the ability to display data in view of my storyboards. This model is just a jumping off point to a much larger project. If you could help that would be great! For now I’ll go back to Chris’s lesson on understanding JSON to see where I went wrong.

I guess the first thing to do is map out what data you want to display. Once you have that decided upon, then you can build your model struct to suit.

Hey Chris,

I go some positive results using a new set of code from CWC tutorial. Here is the code:

import UIKit

class ViewController: UIViewController {

@IBOutlet var greetingsLbl: UILabel!
@IBOutlet var nameLbl: UILabel!



override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    
    // URL
    let url = URL(string: "https://www.goedash.com/_functions/api/DummyData")
    
    guard url != nil else {
        print("Error creating url object")
        return
    }
    
    // URL Request
    var request = URLRequest(url: url!, cachePolicy:
        .useProtocolCachePolicy, timeoutInterval: 10)
    
    // Specify the header
    let header = [
        
        "content-type": "application/json",
       
    ]
    
    request.allHTTPHeaderFields = header
    
    // Specify the body
    let jsonObject = [
    
            "greetings": "",
            "name": ""

    ]
    
    do {
        
        let requestBody = try JSONSerialization.data(withJSONObject: jsonObject, options: .fragmentsAllowed)
        
        request.httpBody = requestBody
   
    }
    catch {
        print("Error catching the data from json")
    }
    // Set the request type
    request.httpMethod = "POST"
    
    // Get the URLSession
    let session = URLSession.shared
    
    // Create the data task
    let dataTask = session.dataTask(with: request) { data, response, error in
        
        // Check for errors
        if error == nil && data != nil {
            
            // Try to parse out the data
            do {
                let dictionary = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String:Any]
                print(dictionary!)
                
            }
            catch {
                print("Error parsing response data")
            }
        }
        
    }
    
    // Fire off the data task
    dataTask.resume()
}

}

And here is the result:

Now using this code which from the CWC tutorial how would you implement the two text objects:

@IBOutlet var greetingsLbl: UILabel!
@IBOutlet var nameLbl: UILabel!

This is the golden egg for me if you could solve this. I’ve tried for days to figure it out.

@coder3000

For what it is worth I managed to decode the json that you originally provided in that sample BUT the json needs to be like this:

{
    "items": [
        {
            "name": "My name is Gilbert",
            "greetings": "Hello world",
            "id": "7ad33209-1223-449b-afbc-c69d20935389",
            "owner": "04c4cdf4-723c-4c3b-a14d-6867c733b2d1",
            "createdDate": "2022-06-26T17:05:18.192Z",
            "updatedDate": "2022-06-27T20:13:13.707Z",
            "title": "User"
        }
    ]
}

It can be all in a single line but is easier to read like this.

I changed the property names that began with an underscore and removed the underscore. I then created a Model like this:

struct Intro: Decodable {
    let items: [Item]
}

struct Item: Decodable, Identifiable {
    let id: UUID
    let name: String
    let owner: UUID
    let title: String
    let greetings: String
    let createdDate: String
    let updatedDate: String
}

I then used some SwiftUI code and an ObservableObject to decode the json from a file in the Bundle, as opposed to downloading it from a server of some sort using a URLSession, just to prove that it could be decoded.

I then uploaded the json file to my ISP server space and used your fetchData code, although modified, to retrieve the json from a remote site and that worked too.

This was the ObservableObject class that includes the fetchLocalData and fetchRemoteData methods:

class ContentViewModel: ObservableObject {
    @Published var items = [Item]()

    init() {
        fetchRemoteData()
    }

    func fetchLocalData() {

        let jsonUrl = Bundle.main.url(forResource: "data", withExtension: "json")
        
        do {
            //  Read the file into a data object
            let jsonData = try Data(contentsOf: jsonUrl!)
            
            let decoder = JSONDecoder()
            do {
                let decodedData = try decoder.decode(Intro.self, from: jsonData)
                self.items = decodedData.items
            } catch {
                print("Unable to decode JSON data \(error.localizedDescription)")
            }
        } catch {
            print("Unable to find JSON data")
        }
    }

    func fetchRemoteData() {
        let urlString = "http://d1058276.myweb.iinethosting.net.au/data.json"
        let url = URL(string: urlString)
        let defaultSession = URLSession(configuration: .default)
        let dataTask = defaultSession.dataTask(with: url!) { data, response, error in

            if error != nil {
                print(error!.localizedDescription)
                return
            }

            do {
                let json = try JSONDecoder().decode(Intro.self, from: data!)
                DispatchQueue.main.async {
                    self.items = json.items
                }
            } catch {
                print(error.localizedDescription)
            }
        }
        dataTask.resume()
    }
}

If you want to take a look at the entire SwiftUI project then let me know.

Oh! Yes please. I would like the entire project. Thanks!

@coder3000

Here’s the DropBox link: Dropbox - coder3000.zip - Simplify your life

This is what I got when I put the link in:

@coder3000
What does your json data now look like?

Everything works great using your url! I need to see what’s going on with url.