Сопоставление ответа JSON с объектами с помощью программирования Rx (Moya)

В настоящее время я пытаюсь изучить программирование 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

Поэтому мне было интересно, может ли кто-нибудь помочь мне понять, почему я не могу превратить ответ в объекты. Спасибо.

=======

Я попытался выполнить обновление модуля, и он все еще не работает. Вот где я привязываю его к 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, он также никогда не будет вызван.


person pls    schedule 09.04.2016    source источник
comment
Можешь попробовать обновить поды? Если это не помогает, запросы выглядят нормально, потому что вы получаете ответ 200. Как вы привязываете trackIssues() к пользовательскому интерфейсу?   -  person sunshinejr    schedule 09.04.2016
comment
Спасибо за ответ. Я сделал обновление модуля, но это не сработало. Я отредактировал код, чтобы включить привязку trackIssues() к пользовательскому интерфейсу.   -  person pls    schedule 09.04.2016
comment
Если массив находится в ключе trains, попробуйте использовать .mapArrayOptional(Train.self, keyPath: "trains") вместо .mapArrayOptional(Train.self).   -  person sunshinejr    schedule 09.04.2016
comment
Это работает. Большое спасибо :-).   -  person pls    schedule 09.04.2016
comment
Без проблем! Я сделал ответ, чтобы помочь другим людям, которые также сталкиваются с той же проблемой.   -  person sunshinejr    schedule 09.04.2016


Ответы (1)


Причина, по которой это не работает, заключается в том, что JSON, полученный с сервера, возвращает словарь, а не массив. Массив, который вы хотите проанализировать, находится под ключом «поезда» в этом словаре. Используемый в этом руководстве метод Moya-ModelMapper также имеет методы для этого использования. Вам просто нужно передать второй аргумент, keyPath: в метод mapArrayOptional().

Итак, ответ на ваш вопрос: заменить:
.mapArrayOptional(Train.self)
на
.mapArrayOptional(Train.self, keyPath: "trains")

person sunshinejr    schedule 09.04.2016
comment
Привет, могу спросить, как мы можем обрабатывать вложенный json? например, данные, необходимые для модели, находятся за несколькими вложенными json в ответ json. А можете мне помочь с этим вопросом? большое спасибо stackoverflow.com/questions/43228253/ - person Lê Khánh Vinh; 05.04.2017