Parse JSON NSDictionary?

Hello all:


I am getting JSON data from a URL and then putting it into an array, and then I need to get that data into an array of objects. Here is the struct and array (actual names hidden for confidentiality):


struct sTest: Codable

{

var a: String

var b: String

var c: String

var d: String

var e: String

var f: String

var g: String

}

var sTestArray = [sTest]()


and I get the data from the URL using this code snippet


if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary

{

let theList: NSArray = jsonObj["data"] as! NSArray


and when I print the array in the Console, this is what I get:


Success

{

data = (

{

a = "a value";

b = "b value";

c = "c value";

d = "d value";

e = "e value";

f = "f value";

g = "g value";

},

and there are 144 data elements.


I am stuck on parsing this into the sTestArray. I have tried setting up a decoder, and also tried using array indexes, but no joy. Can anyone offer any assistance?


Thanks in advance!


John.

Accepted Reply

Assuming your JSON text looks like this:

{
    data: [
        {
            "a" : "a value1",
            "b" : "b value1",
            "c" : "c value1",
            "d" : "d value1",
            "e" : "e value1",
            "f" : "f value1",
            "g" : "g value1"
        },
        {
            "a" : "a value144",
            "b" : "b value144",
            "c" : "c value144",
            "d" : "d value144",
            "e" : "e value144",
            "f" : "f value144",
            "g" : "g value144"
        }
    ]
}

You may need to prepare two structs:

struct Result: Codable {
    var data: [STest]
}
struct STest: Codable {
    var a: String
    var b: String
    var c: String
    var d: String
    var e: String
    var f: String
    var g: String
}

When you successfully prepare your structs, you can decode it like this:

    guard let data = data else {
        print("data invalid")
        return
    }
    do {
        let result = try JSONDecoder().decode(Result.self, from: data)
        let theList = result.data
        //Use `theList` here
        print(theList)
        //...
    } catch {
        print(error)
    }

Replies

How do you get that output? `print(jsonObj)` or `print(theData)` or something else? Why does it include `Success`?

I guess `a`, `b`, `c`, ... are not actual member names. What are the real ones?


If you want to find how to make your codable work, you should better show actual text of the JSON.


And a few more,

- You should better follow the simple coding rule of Swift, type names start with a capital letter. `sTest` does not look like Swift type.

- You have no need to use NSDictionary or NSArray even when using `JSONSerialization`. Use Swift Dictionary or Swift Array

- Better avoid using `try?`. which throws away all info on error

Assuming your JSON text looks like this:

{
    data: [
        {
            "a" : "a value1",
            "b" : "b value1",
            "c" : "c value1",
            "d" : "d value1",
            "e" : "e value1",
            "f" : "f value1",
            "g" : "g value1"
        },
        {
            "a" : "a value144",
            "b" : "b value144",
            "c" : "c value144",
            "d" : "d value144",
            "e" : "e value144",
            "f" : "f value144",
            "g" : "g value144"
        }
    ]
}

You may need to prepare two structs:

struct Result: Codable {
    var data: [STest]
}
struct STest: Codable {
    var a: String
    var b: String
    var c: String
    var d: String
    var e: String
    var f: String
    var g: String
}

When you successfully prepare your structs, you can decode it like this:

    guard let data = data else {
        print("data invalid")
        return
    }
    do {
        let result = try JSONDecoder().decode(Result.self, from: data)
        let theList = result.data
        //Use `theList` here
        print(theList)
        //...
    } catch {
        print(error)
    }

Thanks SO much for the reply! I had set up the structs and gotten the result as you show, but then had used the JSONSerialzation line further on and tried to run the decode on that. I think I read one too many articles and was overcomplicating it.

Is there a way to be able to access the data in theList outside the scope of the "do"? Make it available to the entire ViewController?

It depends on where you write the decoding code.

You should better starrt a new thread with showing enough code. Better include whole class.

I've followed along the given example and tried passing the JSON NSDictonary but I'm getting an error saying that my struct is does not conform to Codeable

{
    "data": [
        {
            "id": 1,
            "attributes": {
                "name": "",
                "description": "",
                "address": "",
                "rate": 0,
                "features": null,
                "rate_computation_period": "",
                "category": "",
                "available": true,
            }
        }
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pageSize": 25,
            "pageCount": 1,
            "total": 1
        }
    }
}