Объедините конвейер декодирования JSON, когда ответ может быть массивом или объектом во время выполнения - PullRequest
1 голос
/ 04 августа 2020

У меня есть API, который может возвращать массив JSON объектов JSON или один объект JSON.

Как мне написать конвейер объединенного издателя, который обрабатывает этот случай?

Обычно я жестко кодирую тип ответа JSON, когда добавляю свой оператор декодирования комбинирования в свой конвейер:

.decode(type: [MyArrayType].self, decoder: JSONDecoder())
.decode(type: MyObjectType.self, decoder: JSONDecoder())

1 Ответ

0 голосов
/ 04 августа 2020

Определенно возможно обновить цепочку издателей и попытаться декодировать массив [SomeDecodable], а в противном случае - отступить от декодирования самого SomeDecodable.

Шаблон заключался бы в том, чтобы обернуть его в a FlatMap, и для устранения сбоя внутри него.

Итак, допустим, у вас есть некий upstream издатель с выводом Data и ошибкой Error, и вы пытаясь расшифровать некоторые общие c типа T: Decodable, это может быть способ приблизиться:

upstream
  .flatMap { data in
     Just(data)
       // attempt to decode as [T]
       .decode(type: [T].self, decoder: JSONDecoder())
       // if successful, publish each element one-by-one
       .flatMap { arr -> AnyPublisher<T, Error> in 
           Publishers.Sequence(sequence: arr).eraseToAnyPublisher()
       }
       // if error, attempt to decode as T, possibly failing
       .tryCatch { _ in Just(data).decode(type: T.self, decoder: JSONDecoder()) }
  }
  // this will be an AnyPublisher<T, Error>
  .eraseToAnyPublisher()
...