Как добавить поле в JSON Moya.Response, которого не было в реальной полезной нагрузке из ответа http

Если бы у меня был:

import Moya
import RxSwift
import ObjectMapper
import Moya_ObjectMapper

provider.request(.callApi(id: id))
      .mapObject(Thing.self)
      .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
      .observeOn(MainScheduler.instance)

...

struct Thing: Mappable, Equatable {

  var id: String?

  init?(map: Map) {
  }

  mutating func mapping(map: Map) {
    id <- map["id"]
  }

Выполнение вызова http API и получение обратно json, например {"id: "123"}, и все отлично работает. Создается новая структура Thing с правильным идентификатором. Но что, если я хочу добавить «изюминку» к Thing и жесткому коду {"id: "123", "flavor": "что-то"}.

то есть давайте просто изменим фактическое тело ответа http и добавим "flavor": "something", прежде чем он попадет в метод .mapObject. Где правильное место, чтобы воспользоваться этим?

И это не просто добавление его в функцию сопоставления в Thing, потому что «что-то» отличается для каждого идентификатора. Может быть вкус: «что-то 1», а затем вкус: «что-то 2». У меня есть это значение в той же области, что и callApi(id: id), поэтому что-то вроде:

provider.request(.callApi(id: id))
      .addJSON("flavor", flavor)
      .mapObject(Thing.self)
      .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
      .observeOn(MainScheduler.instance)

Но .addJSON это то, что я только что придумал. Его не существует. Но для этого должно быть какое-то простое решение?


person Andrew Arrow    schedule 18.06.2017    source источник
comment
закончилось тем, что каждый http-вызов с Alamofire был сделан напрямую, и тогда это было просто. Это все для github.com/andrewarrow/boring_company_chat, если кому-то интересно.   -  person Andrew Arrow    schedule 18.06.2017


Ответы (1)


Попытка изменить фактический JSON кажется грязной и на двух низкоуровневых. Но я был там, так что не судите по мне, работает ли это. :)

Я бы подошел к этому, создав специальную версию методов расширения Moya.Response, доступных в Moya_ObjectMapper.

public extension Response {

  /// Maps data received from the signal into an object which implements the Mappable protocol.
  /// If the conversion fails, the signal errors.
    public func mapObject<T: BaseMappable>(_ type: T.Type, context: MapContext? = nil) throws -> T {
        guard let object = Mapper<T>(context: context).map(JSONObject: try mapJSON()) else {
      throw MoyaError.jsonMapping(self)
    }
   return object
  }

Я бы добавил аналогичный метод, но с дополнительным замыканием параметра (T) -> (T). Таким образом, он по существу вернет сопоставленный объект после выполнения другой карты, которая добавит в нее любую необходимую вам информацию.

person Evan Anger    schedule 21.06.2017