使用 Rx 编程 (Moya) 将 JSON 响应映射到对象

Posted

技术标签:

【中文标题】使用 Rx 编程 (Moya) 将 JSON 响应映射到对象【英文标题】:Mapping JSON response to objects using Rx programming (Moya) 【发布时间】:2016-04-09 12:46:02 【问题描述】:

我目前正在尝试学习 Rx 编程。我发现 Moya 很有趣,并且一直在尝试实现一个简单的网络请求,然后将其映射到我可以用来填充 tableView 的对象。

我一直在关注这个教程:http://www.thedroidsonroids.com/blog/ios/rxswift-examples-3-networking/

我相信我在使用.debug 并获得以下输出时得到了成功的响应:

2016-04-09 13:29:30.398: MyApi.swift:37 (findRepository) -> subscribed
2016-04-09 13:29:30.400: MyApi.swift:35 (findRepository) -> subscribed
2016-04-09 13:29:32.633: MyApi.swift:35 (findRepository) -> Event Next(Status Code: 20..., Data Length: 5747)
2016-04-09 13:29:32.633: MyApi.swift:35 (findRepository) -> Event Completed

这是我正在使用的代码:

let provider: RxMoyaProvider<MyApi>
let repositoryName: Observable<String>

func trackIssues() -> Observable<[Train]> 
    return repositoryName
        .observeOn(MainScheduler.instance)
        .flatMapLatest  name -> Observable<[Train]?> in
            print("Name: \(name)")

            return self.findRepository(name)
        .replaceNilWith([])


internal func findRepository(name: String) -> Observable<[Train]?> 
    print("help")
    return self.provider
        .request(MyApi.Trains(name, "c76a46ce2b3d8685982b/raw/10e86080c3b1beedd46db47f5bb188cc74ce5c78/sample.json"))
        .debug()
        .mapArrayOptional(Train.self)
        .debug()

这是我要映射到的对象:

import Mapper

struct Train: Mappable 

    let distance: String
    let eta: String

    init(map: Mapper) throws 
        try distance = map.from("distance")
        try eta = map.from("eta")
    

我查看了网络响应,想知道是否首先需要抽象“火车”数据。我已经通过映射到以下对象来尝试这个,但运气不好:

import Mapper

struct TrainsResponse: Mappable 

    let trains: String

    init(map: Mapper) throws 
        try trains = map.from("trains")
    

请在此处找到示例 json 响应:http://pastebin.com/Wvx8d5Lg

所以我想知道是否有人可以帮助我了解为什么我无法将响应转换为对象。谢谢。

=======

我已尝试进行 pod 更新,但仍然无法正常工作。这是我将它绑定到 tableView 的地方:

func setupRx() 
    // First part of the puzzle, create our Provider
    provider = RxMoyaProvider<MyApi>()

    // Now we will setup our model
    myApi = MyApi(provider: provider, repositoryName: userName)

    // And bind issues to table view
    // Here is where the magic happens, with only one binding
    // we have filled up about 3 table view data source methods
    myApi
        .trackIssues()
        .bindTo(tableView.rx_itemsWithCellFactory)  (tableView, row, item) in
            let cell = tableView.dequeueReusableCellWithIdentifier("issueCell", forIndexPath: NSIndexPath(forRow: row, inSection: 0))
            cell.textLabel?.text = "Hello"

            print("Hello")

            return cell
        
        .addDisposableTo(disposeBag)

绑定到(我设置单元格的位置)内的代码永远不会被调用。此外,如果我在我的 Train 映射器类中放置一个断点,它也永远不会被调用。

【问题讨论】:

您可以尝试更新 pod 吗?如果它没有帮助,请求似乎没问题,因为你得到了 200 响应。如何将trackIssues() 绑定到 UI? 感谢您的回复。我做了一个 pod 更新,但没有用。我已经编辑了代码以包含我将 trackIssues() 绑定到 UI 的位置。 如果数组在“trains”键中,请尝试使用.mapArrayOptional(Train.self, keyPath: "trains"),而不是.mapArrayOptional(Train.self) 那行得通。非常感谢:-)。 没问题!我已经做出了回答以帮助遇到同样问题的其他人。 【参考方案1】:

它不起作用的原因是从服务器检索的 JSON 返回字典,而不是数组。您要解析的数组位于该字典中的“trains”键下。教程中使用的Moya-ModelMapper 也有这种用法的方法。您只需要在mapArrayOptional() 方法中传递第二个参数keyPath:

所以你的问题的答案是替换:.mapArrayOptional(Train.self).mapArrayOptional(Train.self, keyPath: "trains")

【讨论】:

您好请问如何处理嵌套的json?例如,模型所需的数据位于 json 响应中的一些嵌套 json 后面。可以帮我解决这个问题吗?非常感谢***.com/questions/43228253/…

以上是关于使用 Rx 编程 (Moya) 将 JSON 响应映射到对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 Moya + RxSwift 处理自定义错误响应

使用 Moya 将参数附加到每个网络调用

如何向 Moya.Response JSON 添加一个字段,该字段不在来自 http 响应的真实有效负载中

RxSwift/Moya - 如果通过函数返回序列将不会启动

将 Moya 响应错误转换为定义的类型

使用 Moya 处理缓存