Search code examples
swiftcombine

Combine - how to proceed to decode a local json file if online fetch failed?


I have an up-to-date json file hosted online and a local json file in my Xcode workspace. I would like to proceeed to decode a locally stored file if fetching failed: MyError.fetchError e.g. for no internet connection. This is the pipeline:

func fetchAndDecode<T: Decodable>(url: URL) -> AnyPublisher<T, MyError> {
    fetchURL(url: url)
        .decode(type: T.self, decoder: JSONDecoder())
        .mapError { error in
            if let error = error as? DecodingError {
                return MyError.parsingError
            }  else {
                return MyError.fetchError //here somehow proceed to parse local json file
            }
        }
        .eraseToAnyPublisher()
}

How to achieve this ?


Solution

  • .mapError is the wrong operator because it considers only the Error branch.

    fetchURL returns obviously Data, so before decoding the data you have to replace the fetch error with the local data.

    Before the .decode... line insert

    .replaceError(with: try! Data(contentsOf: Bundle.main.url(forResource: "local", withExtension: "json")!))
    

    and delete the .mapError operator.

    local.json represents the file name of the local file in the bundle.