1

I want to parse this response. Everything else is parsed - except Images. I receive it in a string but then I cannot convert it into a dictionary. This is my model.

struct PropertyList: Decodable {

let result: Property?
let success: Bool = false

struct Property: Decodable {
    let name: String?
    let description: String?
    let propertyType: PropertyType
    let latitude, longitude: String

    let images: String?
    let areaSize:Int?
    let threeSixtyView: String?
    let threeDModel: String?

    enum CodingKeys: String, CodingKey {
        case name
        case propertyDescription = "description"
        case propertyType, latitude, longitude
        case threeDModel = "threeDModel"
        case images = "images"
    }
}
}


struct PropertyType: Codable {
let id: Int
let name, propertyTypeDescription: String

enum CodingKeys: String, CodingKey {
    case id, name
    case propertyTypeDescription = "description"
}
}

API Response :

        "name": "Al Deyar",
        "description": "Al Deyar Villa",
        "propertyType": {
            "id": 709415277471,
            "name": "villa",
            "description": "villa"
        },
        "latitude": "1",
        "longitude": "2",
        "viewOfWater": null,
        "threeDModel": "https://viewer.archilogic.com/?sceneId=80d4b3bb-98de-4279-a867-633bf67c6e72&s=m2fss0p3slst",
        "images": "[{\"id\": 1, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/1BEEA0B6-A2B1-4D5E-837B-9C2B00F46EE4_2048x2048.jpg\"},\n{\"id\": 2, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/984D2D29-2448-4B68-827F-EC912AB9AF14_2048x2048.jpg\"},\n{\"id\": 3, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-_0002_Layer_11_2048x2048.jpg\"},\n{\"id\": 4, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-_0002_Layer_10_ad2d92e2-3740-4d1d-8e9c-ed41cf89c3b2_2048x2048.jpg\"},\n{\"id\": 5, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0001_Layer_21_2048x2048.jpg\"},\n{\"id\": 6, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0044_Layer_5_2048x2048.jpg\"},\n{\"id\": 7, \"image\":\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0042_Layer_3_2048x2048.jpg\"}]"

> Blockquote

My model with values updated

enter image description here

3
  • Why you don't create Image struct with id and image. And after that images will be array of the new struct? Commented Jul 4, 2019 at 6:10
  • 1
    As a proper fix, this should be fixed on the backend side. Commented Jul 4, 2019 at 6:20
  • @m1sh0 I tried it - it doesn't work Gives me error. Commented Jul 4, 2019 at 6:29

3 Answers 3

7

images is a nested JSON string which has to be decoded separately.

A solution is to declare the value containing the nested JSON string as struct (ImageJSON) with a singleValueContainer and decode the string on second level.

I left out the properties which are not in the JSON

let json = """
{
"success" : true,
"result" : {
    "name": "Al Deyar",
    "description": "Al Deyar Villa",
    "propertyType": {
        "id": 709415277471,
        "name": "villa",
        "description": "villa"
    },
    "latitude": "1",
    "longitude": "2",
    "viewOfWater": null,
    "threeDModel": "https://viewer.archilogic.com/?sceneId=80d4b3bb-98de-4279-a867-633bf67c6e72&s=m2fss0p3slst",
    "images":"[{\\"id\\": 1, \\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/1BEEA0B6-A2B1-4D5E-837B-9C2B00F46EE4_2048x2048.jpg\\"},{\\"id\\": 2,\\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/984D2D29-2448-4B68-827F-EC912AB9AF14_2048x2048.jpg\\"},{\\"id\\": 3,\\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-_0002_Layer_11_2048x2048.jpg\\"},{\\"id\\": 4,\\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-_0002_Layer_10_ad2d92e2-3740-4d1d-8e9c-ed41cf89c3b2_2048x2048.jpg\\"},{\\"id\\": 5,\\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0001_Layer_21_2048x2048.jpg\\"},{\\"id\\": 6,\\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0044_Layer_5_2048x2048.jpg\\"},{\\"id\\": 7,\\"image\\":\\"https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0042_Layer_3_2048x2048.jpg\\"}]"
    }
}
"""

struct Response : Decodable {
    let result: Property
    let success: Bool
}

struct Property: Decodable {
    let name: String
    let description: String
    let propertyType: PropertyType
    let latitude, longitude: String

    let images: ImageJSON
    let threeDModel: URL
}

struct PropertyType: Codable {
    let id: Int
    let name, description: String
}

struct Image : Decodable {
    let id : Int
    let image : URL
}

struct ImageJSON : Decodable {
    let images : [Image]

    init(from decoder : Decoder) throws {
        let container = try decoder.singleValueContainer()
        let imageJSONString = try container.decode(String.self)
        let imageJSONData = Data(imageJSONString.utf8)
        images = try JSONDecoder().decode([Image].self, from: imageJSONData)
    }
}

let data = Data(json.utf8)
do {
    let decoder = JSONDecoder()
    let response = try decoder.decode(Response.self, from: data)
    let images = response.result.images.images
    print(images)
} catch {
    print(error)
}
Sign up to request clarification or add additional context in comments.

1 Comment

Even I would say to the backend guy to fix this type of response but on the other side, I would say that it is a perfect solution. Thank you...
2

Try the below code :

Update your json :

let json = """
{
"name": "Al Deyar",
"description": "Al Deyar Villa",
"propertyType": {
    "id": 709415277471,
    "name": "villa",
    "description": "villa"
},
"latitude": "1",
"longitude": "2",
"viewOfWater": null,
"threeDModel":"https://viewer.archilogic.com/?sceneId=80d4b3bb-98de-4279-a867-633bf67c6e72&s=m2fss0p3slst",
"images": [
{"id": 1, "image": "https://neigborhood-images.s3.amazonaws.com/property/1BEEA0B6-A2B1-4D5E-837B-9C2B00F46EE4_2048x2048.jpg"},
{"id": 2, "image": "https://neigborhood-images.s3.amazonaws.com/property/984D2D29-2448-4B68-827F-EC912AB9AF14_2048x2048.jpg"},
{"id": 3, "image": "https://neigborhood-images.s3.amazonaws.com/property/EBARZA-_0002_Layer_11_2048x2048.jpg"},
{"id": 4, "image": "https://neigborhood-images.s3.amazonaws.com/property/EBARZA-_0002_Layer_10_ad2d92e2-3740-4d1d-8e9c-ed41cf89c3b2_2048x2048.jpg"},
{"id": 5, "image": "https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0001_Layer_21_2048x2048.jpg"},
{"id": 6, "image": "https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0044_Layer_5_2048x2048.jpg"},
{"id": 7, "image": "https://neigborhood-images.s3.amazonaws.com/property/EBARZA-furniture_0042_Layer_3_2048x2048.jpg"}
]
}
"""

Update your codable class :

struct Property : Codable {

    let descriptionField : String?
    let images : [Images]?
    let latitude : String?
    let longitude : String?
    let name : String?
    let propertyType : PropertyType?
    let threeDModel : String?
    let viewOfWater : String?

    enum CodingKeys: String, CodingKey {
        case descriptionField = "description"
        case images = "images"
        case latitude = "latitude"
        case longitude = "longitude"
        case name = "name"
        case propertyType = "propertyType"
        case threeDModel = "threeDModel"
        case viewOfWater = "viewOfWater"
    }
}


struct PropertyType : Codable {

    let descriptionField : String?
    let id : Int?
    let name : String?

    enum CodingKeys: String, CodingKey {
        case descriptionField = "description"
        case id = "id"
        case name = "name"
    }
}


struct Images : Codable {
    let id : Int?
    let image : String?
}




if let jsonData = json.data(using: .utf8) {
    let decoder = JSONDecoder()

    do {
        let jsonModel = try decoder.decode(Property.self, from: jsonData)
        print(jsonModel)
    } catch {
        print("Error = \(error)")
    }
}

1 Comment

Thanks a lot - thats the issue. I cant ask the backend developer to change it
1

Create an image type as below,

struct PropertyImage: Decodable {
    var id: Int
    var image: String?
}

Now, get data from the images string and decode an array of property images as below,

if let data = property.images.data(using: .utf8) {
    do {
        let images = try JSONDecoder().decode([PropertyImage].self, from: data)
        images.forEach { image in
           print(image.id)
           print(image.image)
         }

    } catch {
        print(error)
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.