0

Well guys like the title says i have on a response service call an JSON array and i cant find the way to decode with Combine: URLSession.shared.dataTaskPublisher

Service Response: https://codebeautify.org/alleditor/y228809f7

My Request Code:

public func getGasStationDiscounts(requestModel: GasStationDiscountsRequestDomainModel) -> CiMAObservable<GasStationDiscountsDomainModel> {
    guard let url = URL(string: RepositoryConstants.baseURL + String(format: RepositoryConstants.EndPoints.gasStationDiscounts, requestModel.gasStationID)) else {
        return Fail(error: NSError(domain: "URL Invalid", code: 001, userInfo: nil)).eraseToAnyPublisher()
    }
    
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "GET"
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    return URLSession.shared.dataTaskPublisher(for: urlRequest)
        .map(\.data)
        .decode(type: GasStationDiscountsDataModel.self, decoder: JSONDecoder())
        .map { model -> GasStationDiscountsDomainModel in
            model.parseToDomainModel()
        }.eraseToAnyPublisher()
}

Decodable File: https://codebeautify.org/alleditor/y2296aefe

So resuming, my problem is on trying to decode it because its an Array, on my project i'm working with diferent layers like Data, Domain and the Presentation (don't ask about architecture cuz is a new one, CiMA on GitHub) its a Hybrid Viper arch.

Thanks in advance!

EDITED: SOLVED! So finally i found a Solution which don't destroy my architecture. So here the small changes on decodable Files: https://codebeautify.org/alleditor/y22ad811e

and the last changes on the Request:

    public func getGasStationDiscounts(requestModel: GasStationDiscountsRequestDomainModel) -> CiMAObservable<GasStationDiscountsDomainModel> {
    guard let url = URL(string: RepositoryConstants.baseURL + String(format: RepositoryConstants.EndPoints.gasStationDiscounts, requestModel.gasStationID)) else {
        return Fail(error: NSError(domain: "URL Invalid", code: 001, userInfo: nil)).eraseToAnyPublisher()
    }
    
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "GET"
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    return URLSession.shared.dataTaskPublisher(for: urlRequest)
        .map(\.data)
        .decode(type: [GasStationDiscountsDataModel].self, decoder: JSONDecoder())
        .map { model -> GasStationDiscountsDomainModel in
            let stationDiscountsDomainModel = model.map { model -> StationDiscountDomainModel in
                model.parseToDomainModel()
            }
            return GasStationDiscountsDomainModel(stationDiscounts: stationDiscountsDomainModel)
        }
        .mapError { error in
            print(error.localizedDescription)
            return error
        }.eraseToAnyPublisher()
}
1
  • Do not add a solution to the question. If you have a solution, put it in an answer. Question; answer. It's a pretty clear distinction. Answering your own question, and even accepting that answer, is totally legal. Commented Dec 31, 2022 at 1:56

2 Answers 2

1

The response seems to be an array. There is no top level element. Use:

.decode(type: [StationDiscountDataModel].self, decoder: JSONDecoder())
Sign up to request clarification or add additional context in comments.

5 Comments

mmm still without working if you see my code i had a model.parseToDomainModel() and i need it because its working with different layers Data (repositories) Domain (Business)
@coden0w What do you mean by "still without working". Your question was about decoding, was it? Decoding to an array of your structs works for me. And at least for me there seems pretty straight forward to map this to the desired output.
i solved it at final, i will add the solution, in few minutes. thank you burnsi! (for the fast reply to my question :))
@coden0w If this answer helped you solve your problem please consider marking it as the accepted answer (green checkmark).
done! and yes helped me!
0

Create custom operator something like this:

 extension Publisher where Output == Data {
    func customOperator() -> AnyPublisher<GasStationDiscountsDataModel, Never>  {
       return Just(GasStationDiscountsDataModel(data: self as! Data))
              .eraseToAnyPublisher()
       }
 }

And then use it:

 return URLSession.shared.dataTaskPublisher(for: urlRequest)
    .map(\.data)
    .customOperator()
    .map { model -> GasStationDiscountsDomainModel in
        model.parseToDomainModel()
    }.eraseToAnyPublisher()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.