deevee
deevee

Reputation: 1885

JS Object to Swift Struct

I am having difficulties parsing data (JSON-like I get from endpoint) to Swift structs. As it seems data I get from the endpoint is not a valid JSON (at least not all of it looking at the structure of object = (...)), so I can't decode ListStruct.

Should I parse it another way? Any advice much appreciated

Structs I prepared are:

struct Response:Codable {
    let message:String?
    let list:ListStruct?
    let error:Bool?
}

struct ListStruct:Codable {
    let object1:[Object1]?
    let object2:[Object2]?
    let object3:[Object3]?
}

struct Object1:Codable {
id:Int?
name:String?
}
...

Example of data I get from endpoint:

["message": <null>, "list": {
    object1 =     (
                {
            id = 1;
            name = "testing1";
        }
    );
    object2 =     (
                {
            files =             (
            );
            id = 1;
            name = "testing2-1";
            photos =             (
            );
        },
                {
            files =             (
            );
            id = 2;
            name = "testing2-2";
            photos =             (
            );
            systemId = 8;
        }
    );
    object3 =     (
                {
            id = 6;
            name = "testing3-1";
        },
                {

            id = 13;
            name = "testing3-2";
        }
    );
}, "error": 0]

EDIT

How I am trying do decode:

if let result = try JSONDecoder().decode(Response?.self, from: "\(response!)".data(using: .utf8)! ) {
                        print("\(result)")
                    }

Error I am getting:

Error: dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "No string key for value in object around character 6." UserInfo={NSDebugDescription=No string key for value in object around character 6.})))

Upvotes: 1

Views: 1271

Answers (1)

Kamran
Kamran

Reputation: 15268

Most probably, you are passing the wrong data object by creating using string interpolation. If the response type is Data then you don't need to recreate it again in the below line,

if let result = try JSONDecoder().decode(Response?.self, from: "\(response!)".data(using: .utf8)! ) {

Try to pass the response as it is. Shown below,

if let result = try JSONDecoder().decode(Response?.self, from: response!) {

Here is a complete testable example where the correct data object is created using the json in question and error type in Response is changed from Optional Bool to Int,

struct Response:Codable {
    let message:String?
    let list:ListStruct?
    let error: Int?
}

struct ListStruct: Codable {
    let object1:[Object1]?
    let object2:[Object2]?
    let object3:[Object3]?
}

struct Object1: Codable {
    var id:Int?
    var name:String?
}

struct Object2: Codable {
    var id:Int?
    var name:String?
    var systemId: Int?
}

struct Object3: Codable {
    var id:Int?
    var name:String?
}

Usage:

let data = """
{"message": null,

"list": {
"object1": [
{
"id": 1,
"name": "testing1"
}
],
"object2" :     [
{
"files" :             [
],
"id" : 1,
"name" : "testing2-1",
"photos" :             [
]
},
{
"files" :            [
],
"id" : 2,
"name" : "testing2-2",
"photos" :             [
],
"systemId" : 8
}
],
"object3" :     [
{
"id" : 6,
"name" : "testing3-1",
},
{

"id" : 13,
"name" : "testing3-2",
}
]
},

"error": 0
}
""".data(using: .utf8)!

if let result = try! JSONDecoder().decode(Response?.self, from: data) {
        result.list?.object1?.forEach({ obj in
            print(obj.name)
        })
        result.list?.object2?.forEach({ obj in
            print(obj.name)
        })
        result.list?.object3?.forEach({ obj in
            print(obj.name)
        })
}

Output:

Optional("testing1")
Optional("testing2-1")
Optional("testing2-2")
Optional("testing3-1")
Optional("testing3-2")

Upvotes: 2

Related Questions