-2

I have old code from team where they were failing to parse Bool response.

NetworkManager.shared().firebaseTokenService(request: APIRouter.firebasetoken(param as [String : Any]), completion: { (httpResponse, jsonData, error) in
                if httpResponse?.statusCode == 200 {
                        if let responseText = jsonData?.boolValue {
                            if (responseText) {
                                print("Success to send fcm token")
                            } else {
                                print("Failed to send fcm token")
                            }
                        } else {
                            print("Invalid response format")
                        }
                    } else {
                        print("Failed to send fcm token", error?.localizedDescription)
                    }
            })



func firebaseTokenService(request: URLRequestConvertible, completion: @escaping (_ httpResponse: HTTPURLResponse?, _ responseObject:JSON?, _ error: Error?) -> Void)  {
        
        session.request(request, interceptor: nil).validate().responseJSON { (response) in
            switch response.result {
            case .success:
                let json = JSON(response.data as Any)
                completion(response.response, json, nil)
            case .failure(let error):
                completion(nil, nil, error)
            }
        }
    }

The issue I am facing here is that the response is strictly coming as bool either true or false as attached image of postman.

enter image description here

I am getting success code 200, but jsonData is always nil. So please help me to parse the Bool response.

I can't change the code, as they have base class for all these, so only change I have to apply is in this method only.

Any help will be appreciated.

Sagar
  • 1,286
  • 3
  • 19
  • 34
  • @JoakimDanielson JSON – Sagar Jul 15 '23 at 19:49
  • If response get JSON body as response it got stored there in jsonData, but i am not getting response in JSON body, just getting Bool value – Sagar Jul 15 '23 at 19:55
  • You are going to have to look inside your `firebaseToken` code and work out how it is trying to decode JSON. It may be that the response content type header isn't what it expects or something else. We can't help you with the code shown. You could also look at the `httpResponse` object and see if it contains the returned `body` and just parse it yourself – Paulw11 Jul 15 '23 at 20:34
  • You need to show the code of `executeWith(request:)`, how you get `jsonData` exactly from it, and you might need to print also `httpResponse`. – Larme Jul 16 '23 at 18:12
  • For instance, if you used `JSONSerialization`, you need to use `.fragmentsAllowed` in the `options` parameters (but it could also depends on the iOS version)... But since I don't know what you used (outdated `SwiftyJSON`?), it's hard to tell... So show the code of the method, and how you construct `jsonData`. – Larme Jul 16 '23 at 20:38
  • @Larme : Updated the question with code which I did – Sagar Jul 17 '23 at 10:44
  • You are using `responseJSON()`, which is deprecated and which already do a `JSONSerialization` call, and then you call `JSON(response.data as Any)`. I guess that `SwiftyJSON` fails? Is that `SwiftyJSON`? – Larme Jul 17 '23 at 12:03
  • @Larme yes, got the old code from Team and they are saying its failing, Now got the answer why it is. Thanks for help. I need to update the code for this. – Sagar Jul 17 '23 at 12:10
  • `JSON(response.data as Any)` -> `try? JSON(JSON(data: jsonData, options: .fragmentsAllowed)`, and you should be able to call `jsonData.boolValue`. – Larme Jul 17 '23 at 12:18
  • I've updated my answer to reflect the correct change. – Larme Jul 17 '23 at 12:19
  • @Larme : Thank you for help. Sorted the issue. Sometimes this OLD CODES are just bottle neck work – Sagar Jul 17 '23 at 12:34

2 Answers2

1

Alright, I cannot make a concrete-accurate guess with this limited information but, it seems like the response might be malformed. Which I mean by saying malformed is that, there could be an issue with the way the server is generating the response.

You mentioned that the response code is 200 which is cool, but jsonData is nil which is bad, and the response is a boolean which is weird. With the limited information you provided, my best guess is that the response is not a JSON object.

In order to handle this situation (if thats the case), you can handle the plain text response by updating your code:

NetworkManager.shared().executeWith(request: APIRouter.firebasetoken(param)) { (httpResponse, jsonData, error) in
    if httpResponse?.statusCode == 200 {
        if let responseText = jsonData?.stringValue {
            if responseText == "true" {
                print("Success to send fcm token")
            } else {
                print("Failed to send fcm token")
            }
        } else {
            print("Invalid response format")
        }
    } else {
        print("Failed to send fcm token", error?.localizedDescription)
    }
}

You can also check if the server is setting the Content-Type header correctly. It should be set to application/json to indicate that the response is in JSON format. But I don't have the best knowledge on that.

We can understand your issue with additional information. Please correct me if I got your problem wrong. Hope we can solve it.

leopanic13
  • 62
  • 5
  • `true` is valid JSON. – Paulw11 Jul 15 '23 at 22:01
  • I thought about that but isn't it supposed to be **"true"** to become a valid JSON? With the quotation marks ? – leopanic13 Jul 15 '23 at 22:47
  • That would be a string. Without quotation marks, it is a boolean – Paulw11 Jul 15 '23 at 23:39
  • @leopanic13: thanks for input. I know response getting directly bool is weired, I have requested backend to check, but seems updating it will take lot of process. jsonData is in JSON format, but response is coming in bool either TRUE or FALSE. So your condition if let responseText = jsonData?.stringValue won’t working as jsonData is always nil. Need something which will directly parse bool response when status code is 200. Thanks – Sagar Jul 16 '23 at 16:41
  • https://stackoverflow.com/questions/76695495/parse-bool-response-using-alamofire?noredirect=1#comment135231266_76695495 should be the correct way to parse the JSON being only a boolean – Larme Jul 17 '23 at 12:42
0

Without knowing how you get jsonData in (httpResponse, jsonData, error), it's hard to tell what's wrong.

But, if we use let data = Data("true".utf8), having a only a boolean as JSON is valid, a little strange (ie uncommon), but valid JSON. But to be able to parse it, we need to add some options to JSONSerialization.

let value = try JSONSerialization.jsonObject(with: data) //Fails
let value = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) //Success

You need to use .fragmentsAllowed that should allow String, Number, Bool as top level and not only Array/Dictionary (ie "list" or "objects").

You can also directly use Codable:

let value = try JSONDecoder().decode(Bool.self, from: data) //Success

Seeing .stringValue, .bool I suspect you use SwiftyJSON (or assimilated), I strongly suggest to use Codable if possible.

Side note, in the encoding (and so maybe in the decoding at some point), there could be limitation due to iOS versions, see related question

Using SwiftyJSON, you need to allow fragments.

To do so:

let json = JSON(response.data as Any)

===>

let json = try? JSON(data: response.data, options: .fragmentsAllowed)

And then, you should be able to do jsonData.boolValue.

Larme
  • 24,190
  • 6
  • 51
  • 81