Valid JSON, but 'Cocoa error 3840' from AF

2019-04-08 02:06发布

问题:

I've been hacking away for hours trying to solve this problem to no avail - it seems like my only option is to post here to see if anyone can shed some light on this issue. It may be an issue with AFNetworking, or (more likely), it may be an issue with my code.

The code I am using works perfectly for 99% of the operations within my application. I am developing an app that leverages Elastic Search by building JSON searches, sending them off and receiving a response from the server.

Here is an example of the JSON that is returned:

{
    "took": 4,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": null,
        "hits": [
            {
                "_index": "asx",
                "_type": "61a88d3848b00655d9aa59db70847318",
                "_id": "b91f9257744fedb4ef1c127e275c127c",
                "_score": null,
                "_source": {
                    "value": "22/06/1998"
                },
                "sort": [
                    4.439049394553e-312
                ]
            }
        ]
    }
}

Now, plugging this into jsonlint.com (and knowing a bit about JSON formatting), it's easy to see that this is valid JSON.

I am using an AFHTTPClient subclass in order to POST my request and receive data. Here is the code I am using to POST:

[super postPath:path parameters:parameters success:^(AFHTTPRequestOperation *operation, NSDictionary *response) {
    NSData *responseData = [(AFJSONRequestOperation *)operation responseData];
    NSDictionary *responseDictionary;

    if (responseData != nil) {
        responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:NULL];
    }

    if (success) {
        success(operation, responseDictionary);
    }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSData *responseData = [(AFJSONRequestOperation *)operation responseData];
    NSDictionary *responseDictionary;

    if (responseData != nil) {
        responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:NULL];
    }

    if (failure) {
        failure(operation, error, responseDictionary);
    }
}];

Nothing really special here, I'm just turning the response into some JSON.

However, the problem is that for this in particular request, AFNetworking is deeming the response as a failure, so the code in the failure block is the only code being executed. I am getting the following error:

(lldb) po error
$1 = 0x0adbc710 Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Number wound up as NaN around character 279.) UserInfo=0xad968d0 {NSDebugDescription=Number wound up as NaN around character 279.}

The JSON contains an exponential number in it (4.439049394553e-312 specifically), however this is valid number and should be able to be parsed. I get the same NSError when I try to parse the response data using NSJSONSerialization. Just to clarify - AFNetworking is giving me the same error message as NSJSONSerialization does.

I cannot find anyone else who is having the same issue as me, and cannot figure out why my JSON can't be parsed. It's leaving my app with a very large bug which I cannot fix.

If anyone could shed some light on this issue, that'd be great. If it's not an issue with AFNetworking, if you could point me to a helpful resource that would also be awesome. Of course, if you require any more information, please do ask

Thank you.

回答1:

NSJSONSerialization uses NSDecimalNumber to represent numbers, and

[NSDecimalNumber decimalNumberWithString:@"4.439049394553e-312"]

already returns NaN, because NSDecimalNumber can represent only numbers

mantissa x 10^exponent         where `-128 <= exponent <= 127`.

So this seems to be a "restriction" (or bug) of NSJSONSerialization, that it works only with numbers in a certain range.

I made a quick test with "SBJsonParser" and it had the same problem.