I have the following model:
struct Book: Codable, Identifiable {
var id: Int
var title: String
var author: String
}
struct BookWrapper: Codable {
var books: [Book]
}
and JSON:
{
"books": [
{
"id": 1,
"title": "Nineteen Eighty-Four: A Novel",
"author": "George Orwell"
}, {
"id": 2,
"title": "Animal Farm",
"author": "George Orwell"
}
],
"errMsg": null
}
I'm trying to grab data using Combine, but cannot find a way how to go around that books array. In case of flat data I would use following:
func fetchBooks() {
URLSession.shared.dataTaskPublisher(for: url)
.map{ $0.data }
.decode(type: [Book].self, decoder: JSONDecoder())
.replaceError(with: [])
.eraseToAnyPublisher()
.receive(on: DispatchQueue.main)
.assign(to: &$books)
}
I tried to use BookWrapper.self, but it doesn't make sense. Is there any elegant way how to solve it?
You can just map
the books
property of BooksWrapper
before it gets to your assign
:
func fetchBooks() {
URLSession.shared.dataTaskPublisher(for: url)
.map{ $0.data }
.decode(type: BookWrapper.self, decoder: JSONDecoder())
.replaceError(with: BookWrapper(books: [])) //<-- Here
.map { $0.books } //<-- Here
.receive(on: DispatchQueue.main)
.assign(to: &$books)
}