Search code examples
iosjsonswiftcombineurlsession

Retrieve String from `.dataTaskPublisher`


I am trying to return just a string from my node.js Express server. It's a basic server that returns "hello, world!" but not as a JSON object but as a regular string. Here is my code from my request.

URLSession
    .shared
    .dataTaskPublisher(for: request)
    .map(\.data)
    .decode(type: String.self, decoder: decoder)
    .receive(on: DispatchQueue.main)

I think I'm doing it right but I get this but when I run it, I get this error: The data couldn't be read because it isn't in the correct format.

Update

So, as per the comments, I am not returning JSON so I can't use the JSONDecoder. That said, I wanted to use this in a generic fashion and some APIs will return JSON some will return Strings and some will return Ints and some will return Array<Codable>. Is there a way to use combine to try and get these values back from my various API endpoints?

I know that I can do something like this:

URLSession
    .shared
    .dataTaskPublisher(for: request)
    .map(\.data)
    .compactMap { String(data: $0, encoding:. utf8) }
    .receive(on: DispatchQueue.main)

but I want to be able to call each of my endpoints with this function. Can anybody help?


Solution

  • You don't need a decoder, just convert data to string using a String initializer.

    var cancels: Set<AnyCancellable> = []
    
    func fetchData() {
    
        URLSession
            .shared
            .dataTaskPublisher(for: request)
            .map(\.data)
            .compactMap { String(data: $0, encoding:. utf8) }
            .receive(on: DispatchQueue.main)
            .sink (
                receiveCompletion: {
                    print("Completion: \($0)")
                },
                receiveValue: { result in
                    print("String: \(result)")
                })
            .store(in: &cancels)
    }