sean7512 / RestEssentials

Lightweight REST and JSON library for Swift.
MIT License
37 stars 12 forks source link

Weird issue when evaluating for .int on a raw value. #16

Closed aravasio closed 7 years ago

aravasio commented 7 years ago

Ok, this is super weird and, as far as I understand it, it's hard to believe I did not come across this sooner.

Given the following JSON

{
    "error_code" = 02;
    "error_description" = "Invalid credentials";
    result = 1;
}

if I evaluate as such:

if let errorCode = json["error_code"].int, errorCode != 5 {
    //code
}

it will not enter, since the .int evaluation will return nil. It seems the issue is in the numerical eval,

public var numerical: NSNumber? {
        return raw as? NSNumber
}

Printing those same cases gives the following results:

(lldb) po self.raw
02
--------

(lldb) po raw as NSNumber
Could not cast value of type 'NSTaggedPointerString' (0x1066f4cd8) to 'NSNumber' (0x1056fe600).
error: warning: couldn't get required object pointer (substituting NULL): Couldn't load 'self' because its value couldn't be evaluated

error: Execution was interrupted, reason: signal SIGABRT.
The process has been returned to the state before expression evaluation.
--------

(lldb) po self.raw as Int
Could not cast value of type 'NSTaggedPointerString' (0x1066f4cd8) to 'NSNumber' (0x1056fe600).
error: warning: couldn't get required object pointer (substituting NULL): Couldn't load 'self' because its value couldn't be evaluated

error: Execution was interrupted, reason: signal SIGABRT.
The process has been returned to the state before expression evaluation.
--------

(lldb) po self.raw as? String
▿ Optional<String>
  - some : "02"

Any ideas on what might be causing this?

It might be worth noting that "error_code" : 2 on the actual server response, for some reason during conversions and passing, RestEssentials seems to convert it to 02, but on postman it's just 2. No idea how relevant this might be, but I'm putting this out there.

sean7512 commented 7 years ago

@aravasio I created a unit test for your situation and I cannot reproduce. See commit: https://github.com/sean7512/RestEssentials/commit/4253b19acb76609a119c9c233f608b84e1b2ae1c

You can even change error_code to 02 on the post and it still succeeds. So httpbin will just respond back with the same data that was posted to it. It looks as if your number 2 is a string. The server isn't sending it as a string, is it? If it has quotes around it, then you will absolutely see the issue you have above.

Even so, if you are using Swift 4, I would highly recommend using the Codable protocol and stop parsing raw json manually, Codable is a much safer solution.

aravasio commented 7 years ago

Yeah, you're right. I don't know where I got the Postman info, but now it definitely shows a "02" for that value, making it a string.

You can close this. It's clear it's a misunderstanding on our side about how API works, not the library.

Thanks