iOSDev
iOSDev

Reputation: 336

How to create simple codable struct from complex json

I receive a complex json response from the API something similar to this.

{
    "result": "success",
    "count": 100,
    "details": [{
            "unnecessaryDetails": "something",
            "area": {
                "name": "Test1"
            }
        },
        {
            "unnecessaryDetails": "something",
            "area": {
                "name": "Test2"
            }
        },
        {
            "unnecessaryDetails": "something",
            "area": {
                "name": "Test3"
            }
        }
    ]
}

My struct is

struct Person {
    var name: String
}

struct Response {
    var result: String
    var count: Int
    var details: [Person]
}

I don't want to create properties for everything I receive from the response. I can't ask the backend developer to give the necessary details only. How to avoid unnecessary details and create struct with require details only?

Upvotes: 0

Views: 77

Answers (2)

vadian
vadian

Reputation: 285069

You can skip intermediate arrays and dictionaries with nested containers.

struct Person : Decodable {
    let name: String
}

struct Response : Decodable {
    let result: String
    let count: Int
    let details: [Person]

    enum CodingKeys: String, CodingKey { case result, count, details }
    enum DetailCodingKeys: String, CodingKey { case area }

    init(from decoder : Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        result = try container.decode(String.self, forKey: .result)
        count = try container.decode(Int.self, forKey: .count)
        var detailContainer = try container.nestedUnkeyedContainer(forKey: .details)
        var people = [Person]()
        while !detailContainer.isAtEnd {
            let areaContainer = try detailContainer.nestedContainer(keyedBy: DetailCodingKeys.self)
            let person = try areaContainer.decode(Person.self, forKey: .area)
            people.append(person)
        }
        details = people
    }
}

However the effort is much bigger than adding the extra struct

struct Response : Decodable {
    let result: String
    let count: Int
    let details: [Detail]
}

struct Detail : Decodable {
    let area : Person
}

struct Person : Decodable {
    let name: String
}

Upvotes: 1

Sharad Paghadal
Sharad Paghadal

Reputation: 2154

You can use Codable to parse only property you want to parse and rest of all will be ignored, If you want to parse json in 2 separate models, you can follow this question's answer.

Is it possible to decode single level JSON into 2 separate models?

Upvotes: 0

Related Questions