Hey! I'm just starting off with RxSwift/RxMoya and trying to figure out something that seems like it should be very simple.
I have an HTTP request that returns a data array in the following format:
{data:
{results: [...]
}
So, the response isn't a flat JSON Array, there's some cascading.
So the following code would clearly not work.
self.provider
.request(Marvel.Characters(startsWidth: "Iron", limit: nil, offset: nil))
.debug()
.mapArrayOptional(MarvelCharacter.self)
So, I guess I need to some how map the response to expose just the results field before passing it to mapArrayOptional ? Or there's a more global way to define the response structure expected from the server?
Would appreciate your help on this :)
Thanks
Shai
Hey Shai!
I'm afraid there is no direct solution other than mapping response to have the top object that should be the array with objects. 馃槩
Thanks @sunshinejr!
How would that look? I need to map from one Response to a new Response and pass that? Could you help with some sample code?
Although I don't use RxSwift, I have done something similar for ReactiveCocoa and Argo. This might point you in the right direction.
Actually, thinking about it again, my solution does not really work around your problem. However, Argo has a way to extract an object based on a root key.
Sure! Here I have a method that gets a user by repository name. Let's say I give name Moya/Moya, it does the request here, and retrieves the owner object to parse it:
func getUser(byRepoName name: String) -> Observable<User> {
return self.provider
.request(GitHub.Repo(fullName: name))
.debug()
.map { response -> Response in
guard let responseDict = try? response.mapJSON(),
owner: AnyObject = responseDict["owner"],
newData = try? NSJSONSerialization.dataWithJSONObject(owner, options: NSJSONWritingOptions.PrettyPrinted) else {
return response
}
let newResponse = Response(statusCode: response.statusCode, data: newData, response: response.response)
return newResponse
}
.mapObject(User.self)
}
Edit: You could also use our extension for Argo, which @aschuch pointed out. 馃挭
Perfect @sunshinejr ! That's exactly what I tried to do and started doing but thanks for refining that.
Is there any way to do that globally? meaning, for every request? because this data structure (data->results->actual array) is global to the entire API I'm using.
Also thanks for your attempt to assit @aschuch ! :]

Sure! You can make your own mapper extensions for it:
extension ObservableType where E == Response {
func marvelMapArrayOptional<T: Mappable>(type: T.Type) -> Observable<[T]?> {
return map { response -> Response in
// your map
}
.mapArrayOptional(type)
}
}
Just copy your map code above and you should be fine. And then you could use marvelMapArrayOptional instead of mapArrayOptional. You could also do a more generic method if you would like to do it for more methods like mapObject and so on.
extension ObservableType where E == Response {
private func marvelMapResponse() -> Observable<E> {
return map { response -> Response in
// your map
}
}
func marvelMapArrayOptional<T: Mappable>(type: T.Type) -> Observable<[T]?> {
return marvelMapResponse()
.mapArrayOptional(type)
}
}
Hope it helps! 馃帀
Perfect! Thank you! :]
Is there a Moya slack channel or something of sorts or all questions should be filed here? I'm sure more questions will pop as I start digging deeper into this.
Unfortunately we don't have a slack channel, but you could try asking on the RxSwift channel if it is more connected to RxSwift, or on this slack for ios-devs, they are all very helpful. Of course you could still ask the questions on here, no problem with that as well 馃帀
So another question I had is , Is there a way to merge two maps together ?
e.g. , I'm mapping something likes this
{"thumbnail":
{"path": "http://some.path.to/file",
"extension": "jpg"}
}
Right now in my Mappable I'm doing
try thumbPath = map.from("thumbnail.path")
but I would like thumbPath to include both thumbnail.path and thumbnail.extension, concatenated together. Any way to merge those?
That is actually a question for Mapper rather than Moya itself, so please make an issue there. Other than that it would be really helpful if you could make new issues as the questions go, it will be then useful for other people if they need the answer as well (rather than scrolling).
I think that we have resolved current issue, so I'm closing it for now. Thanks!
Most helpful comment
Sure! Here I have a method that gets a user by repository name. Let's say I give name Moya/Moya, it does the request here, and retrieves the owner object to parse it:
Edit: You could also use our extension for Argo, which @aschuch pointed out. 馃挭