0

I'm receiving some paginated JSON response through my API that looks something like this:

page 1:

{
    "count": 96,
    "next": "http://127.0.0.1:8000/id=5/?page=2",
    "previous": null,
    "results": [
        {
            "id": 10,
            "book_name": "Book name",
            "book_id": 70,
            "chapter_number": 1,
            "verse": "Verse title here",
            "verse_number": 1,
            "chapter": 96
        },
        {
            "id": 198,
            "book_name": "Book Name",
            "book_id": 70,
            "chapter_number": 8,
            "verse": "Text here",
            "verse_number": 5,
            "chapter": 103
        }
    ]
}

As I move through the paginated result, ie calling: http://127.0.0.1:8000/id=5/?page=2 I'll get new values in the results array.

page 2:

{
    "count": 96,
    "next": "http://127.0.0.1:8000/id=5/?page=3",
    "previous": "http://127.0.0.1:8000/id=5/",
    "results": [
        {
            "id": 206,
            "book_name": "Book on Second page",
            "book_id": 70,
            "chapter_number": 8,
            "verse": "yadda yadda",
            "verse_number": 13,
            "chapter": 103
        },
        {
            "id": 382,
            "book_name": "Book on second page..",
            "book_id": 70,
            "chapter_number": 15,
            "verse": "Verse here",
            "verse_number": 12,
            "chapter": 110
        }
    ]
}

How would I structure my struct/fix my decoding so I can append the values of results from the JSON while still updating count, next and previous as I go through ..?page=3, ..?page=4 etc

Currently, my struct looks like this:

struct VersesSearchResult: Decodable {
    var results: [Verse]
    var count: Int
    var next: String?
    var previous: String?
}

When doing the decoding, I'm not sure what the syntax should be like to append results to the struct, and update next, previous, and count. So far I got this

...
let verses = try JSONDecoder().decode(VersesSearchResult, from: safeData)
DispatchQueue.main.async {
    // somehow need to get this to work - not entirely sure how
    // where results gets appended, while the rest in the JSON values gets updated
   // obviously I can't do as below:
    self.verseSearchResult.append(contentsOf: verses.results)
    self.verseSearchResult = verses
}
...
erikvm
  • 858
  • 10
  • 30
  • That was just an unfinished example - not sure how to proceed. If you're referring to the `let verses = .....` part. I'm not doing anything in there right now - just wanted to display some information to make it clear what it is I wish to achieve – erikvm Oct 03 '21 at 21:08
  • What is unclear? – erikvm Oct 04 '21 at 07:10
  • I don't know how it can be unclear. Frankly, I'm unclear as to what you think is unclear. Do you need the boilerplate code for making the API call? – erikvm Oct 04 '21 at 07:17
  • Not offended at all! Just trying to understand how I can make it more clear and perhaps update the original question – erikvm Oct 04 '21 at 08:16
  • Well, the idea is that only part of the JSON should be appended, more specifically, the `results` part. I don't want to re-append `count`, `next` and `previous`. That part should just be "overwritten" so to say. Here's a gist with the struct(s) and the API call itself: https://gist.github.com/erikvlm/237a8668f58d82df3e855fecb1d42d74 My "hack" is that I decode two separate structs in the same API call now, not sure if its the best way though – erikvm Oct 04 '21 at 09:02
  • Sure, that works, but what about the `count`, `next` and `previous`? Where should I store that. The whole `(self.verseSearchResult.append(contentsOf: verses.results))` part would only take care of the `results` array from the json – erikvm Oct 04 '21 at 10:25
  • Okay, well, I did write the following: How would I structure my struct/fix my decoding so I can append the values of results from the JSON while still updating count, next and previous as I go through ..?page=3, ..?page=4 etc – erikvm Oct 04 '21 at 10:51

1 Answers1

0

Decode to a temprary instance of the type, then process those properties into your main instance. Depending how you want to process the data, it'll look something like this

extension VersesSearchResult {

  mutating func update(with new: VersesSearchResult) {
    results.append(new)
    count = new.count
    next = new.next
    prev = new.prev
  }
}

and then in your completion block

let newVerses = try JSONDecoder().decode(VersesSearchResult, from: safeData)
self.verses.update(with: newVerses)

If needs be force the update onto the main thread.

You should also handle failure in the 'try' either with a do...catch or other approach.

flanker
  • 3,840
  • 1
  • 12
  • 20
  • I ended up doing something like this: https://gist.github.com/erikvlm/237a8668f58d82df3e855fecb1d42d74 Where I just decode two structs in one api call - not sure if this is an ugly hack or bad practice to use the JSONDecoder() twice? – erikvm Oct 04 '21 at 06:55