iosjsonswiftswift4

Parsing a JsonObject in Swift 4 from an URL


It seems for me this is a very simple task, but even after a lot of researching and trying I can't get it working...

So I have for example this URL, for what I understand this is a api to an JSONObject?!

http://api.geekdo.com/api/images?ajax=1&gallery=all&nosession=1&objectid=127023&objecttype=thing&pageid=357&showcount=1&size=thumb&sort=recent

If I open this link in my browser I get the following result:

{"images":[{"imageid":"1567153","imageurl_lg":"https://cf.geekdo-images.com/images/pic1567153_lg.jpg","name":null,"caption":"White power tiles","numrecommend":"6","numcomments":"0","user":{"username":"manosdowns","avatar":"1","avatarfile":"avatar_id33829.jpg"},"imageurl":"https://cf.geekdo-images.com/6fCr14v025ZKYhXRMnbhYR16Ta8=/fit-in/200x150/pic1567153.jpg"}],"config":{"sorttypes":[{"type":"hot","name":"Hot"},{"type":"recent","name":"Recent"}],"numitems":402,"endpage":402,"galleries":[{"type":"all","name":"All"},{"type":"game","name":"Game"},{"type":"people","name":"People"},{"type":"creative","name":"Creative"}],"categories":[{"type":"","name":"All"},{"type":"BoxFront","name":"BoxFront"},{"type":"BoxBack","name":"BoxBack"},{"type":"Components","name":"Components"},{"type":"Customized","name":"Customized"},{"type":"Play","name":"Play"},{"type":"Miscellaneous","name":"Miscellaneous"},{"type":"Mature","name":"Mature"},{"type":"uncat","name":"Uncategorized"}],"licensefilters":[{"type":"","name":"Any"},{"type":"reuse","name":"Copying allowed"},{"type":"commercial","name":"Commercial use allowed"},{"type":"modify","name":"Modification allowed"}],"datefilters":[{"value":"alltime","name":"All Time"},{"value":"today","name":"Today"},{"value":"twodays","name":"Two Days"},{"value":"last7","name":"Last 7 Days"},{"value":"last30","name":"Last 30 Days"},{"value":"year","name":"Last 365 Days"}],"filters":[{"name":"Licenses","listname":"licensefilters","type":"licensefilter"},{"name":"Category","listname":"categories","type":"tag"},{"name":"Gallery","listname":"galleries","type":"gallery"}]}}

Now my first attempt was to parse this link the way I parse homepages:

    guard let myURL = URL(string: link) else {                                                 >             print("Error: \(link) doesn't seem to be a valid URL")
        return
    }

    do {
        link = try String(contentsOf: myURL, encoding: .ascii)
    } catch let error {
        print("Error: \(error)")
    }

But this doesn't work as I now understand that's because this is JSON coded?!

I searched for parsing JSON and found some explanations for encoding and decoding, but my problem is that in all examples given, the explanations start by "having" already the contents of the JsonObject. My problem is that I can read the contents of the URL in the browser but I would need the content of the URL in Xcode itself, so I can parse it?!

So in my specific case I would only need the content of "imageurl_lg"

...I would know how to do it if I could display the content I can see in my browser also in Xcode - but how do I get the contents of the link into Xcode?

For reference, I also read following instructions, but couldn't apply them to my example... https://www.raywenderlich.com/172145/encoding-decoding-and-serialization-in-swift-4

https://grokswift.com/json-swift-4/

and some more but they didn't help me...


Solution

  • You need to use a URLSession task to do this, and after that you need to use JSONSerialization in this example I return a dictionary of [String:Any] you can convert it to whatever Model you need

    Use this Code

    func fetchData(completion: @escaping ([String:Any]?, Error?) -> Void) {
        let url = URL(string: "http://api.geekdo.com/api/images?ajax=1&gallery=all&nosession=1&objectid=127023&objecttype=thing&pageid=357&showcount=1&size=thumb&sort=recent")!
    
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else { return }
            do {
                if let array = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any]{
                    completion(array, nil)
                }
            } catch {
                print(error)
                completion(nil, error)
            }
        }
        task.resume()
    }
    

    How use it

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        fetchData { (dict, error) in
            debugPrint(dict)
        }
    }
    

    Result Log printed

    Optional(["config": {
        categories =     (
                    {
                name = All;
                type = "";
            },
                    {
                name = BoxFront;
                type = BoxFront;
            },
                    {
                name = BoxBack;
                type = BoxBack;
            },
                    {
                name = Components;
                type = Components;
            },
                    {
                name = Customized;
                type = Customized;
            },
                    {
                name = Play;
                type = Play;
            },
                    {
                name = Miscellaneous;
                type = Miscellaneous;
            },
                    {
                name = Mature;
                type = Mature;
            },
                    {
                name = Uncategorized;
                type = uncat;
            }
        );
        datefilters =     (
                    {
                name = "All Time";
                value = alltime;
            },
                    {
                name = Today;
                value = today;
            },
                    {
                name = "Two Days";
                value = twodays;
            },
                    {
                name = "Last 7 Days";
                value = last7;
            },
                    {
                name = "Last 30 Days";
                value = last30;
            },
                    {
                name = "Last 365 Days";
                value = year;
            }
        );
        endpage = 402;
        filters =     (
                    {
                listname = licensefilters;
                name = Licenses;
                type = licensefilter;
            },
                    {
                listname = categories;
                name = Category;
                type = tag;
            },
                    {
                listname = galleries;
                name = Gallery;
                type = gallery;
            }
        );
        galleries =     (
                    {
                name = All;
                type = all;
            },
                    {
                name = Game;
                type = game;
            },
                    {
                name = People;
                type = people;
            },
                    {
                name = Creative;
                type = creative;
            }
        );
        licensefilters =     (
                    {
                name = Any;
                type = "";
            },
                    {
                name = "Copying allowed";
                type = reuse;
            },
                    {
                name = "Commercial use allowed";
                type = commercial;
            },
                    {
                name = "Modification allowed";
                type = modify;
            }
        );
        numitems = 402;
        sorttypes =     (
                    {
                name = Hot;
                type = hot;
            },
                    {
                name = Recent;
                type = recent;
            }
        ); }, "images": <__NSSingleObjectArrayI 0x600000010710>( {
        caption = "White power tiles";
        imageid = 1567153;
        imageurl = "https://cf.geekdo-images.com/6fCr14v025ZKYhXRMnbhYR16Ta8=/fit-in/200x150/pic1567153.jpg";
        "imageurl_lg" = "https://cf.geekdo-images.com/images/pic1567153_lg.jpg";
        name = "<null>";
        numcomments = 0;
        numrecommend = 6;
        user =     {
            avatar = 1;
            avatarfile = "avatar_id33829.jpg";
            username = manosdowns;
        }; } ) ])
    

    Updated fixing "App Transport Security has blocked a cleartext" error

    Adjust your info.plist

    enter image description here