1

My JSON structure looks like this:

{
    "code": 200,
    "status": "Ok",
    "etag": "7232324423",
    "data": {
        "offset": 0,
        "limit": 25,
        "results": [{
                "id": 1011244,
                "name": "Miss Nesbit",
                "description": "",
                "modified": "2018-04-04T20:15:35-0400",
                "thumbnail": {
                    "path": "http://i.annihil.us/u/prod/i/mg/8/70/4c002efc322e3",
                    "extension": "jpg"
                }
            },
            {
                "id": 1011244,
                "name": "Miss Solis",
                "description": "",
                "modified": "2018-09-04T20:15:35-0400",
                "thumbnail": {
                    "path": "http://i.annihil.us/u/prod/i/mg/8/70/4c002efc382e3",
                    "extension": "jpg"
                }
            }
        ]
    }
}

I want to parse the results in a struct as follows:

struct Character: Codable {
    let id: Int
    let name: String
    let thumbnail: Thumbnail
    let description: String
}

However I'm a bit confused about where I specify I only want the results part ? Would I do it when implementing Decodable as follows?

let container = try decoder.container(keyedBy: CodingKeys.self)
let data = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
let results = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .results)

Or do we have to map out each nested section? ANy help or guidance would be so appreciated! :)

1
  • 1
    Character is a native Swift type. You should choose an alternative name for your struct Commented Sep 28, 2018 at 23:38

2 Answers 2

3

Mapping out the relevant keys is necessary to drill down for you, yes.

You can use app.quicktype.io to get started fast and remove the non-relevant keys if you really don‘t want to parse the rest or leave it there if you may want to use it later.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the response. So in this case, would : code, status, etag, data be relevant and then i can drill down within data to get the results? I thought I'd be able to ignore the outer part but I guess i'm wrong!
@vanilla_splsh Only let data: DataStruct is relevant from the first level, so you and Swift know there is a data-field you can drill into. This DataStruct then has a let results: [CharacterStruct] field, so you can access the array encoded in JSON as an Array inside Swift. Here is a tutorial on the Codable-API. You can ignore everything except where he embeds one struct into another and an array into a struct/class. If you want to do this manually you can use differing CodingKey enums per level & class.
Thank you for your help, makes complete sense now and I got it working!
2

You can use my extension helper NestedDecodable, which allows you to extract Decodable from a keyPath. It adds this method to JSONDecoder:

decoder.decode(Class, from: Data, keyPath: String)

A key path specifies the nested path to the model you want, separated by .

So using your example, this works (tested):

let characters = try decoder.decode([Character].self, from: data, keyPath: "data.results")

Internally, it creates a wrapper struct to hold your target Decodable class, split keyPath by ., then for-loop each key down until it reaches the final keyed decoding container, decode that model and returns. Ref

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.