12

I'm sending this json response from server for a request to my IOS 7 app.

{
 "root": {
    "success": "1",
    "message": "Successfully retrieved data.",
    "data": {
        "records": [
            {
                "receipt_key": "xxxxxxxx",
                "receipt_id": "xxxxxxxx",
                "store_name": "xxxxxx",
                "amount": "xxxx",
                "date_purchase": "xxxxxxxx",
                "is_processed": "x",
                "created_on": "xxxxxxxx",
                "modified_on": "xxxxxxxx",
                "modified_on_millis": "xxxxxxxx",
                "user_folder": "xxxxxxxx",
                "category_id": "xxxxxxxx",
                "is_deleted": "x",
                "currency_id": "xxxxxxxx"
            }
        ]
    }
}
}

I use the following code for parsing the above json to NSDictionary object.

 NSMutableDictionary *json=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];

But I'm getting this error on the above code.

Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x8a8a700 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

sathiamoorthy
  • 1,488
  • 1
  • 13
  • 23
LvN
  • 701
  • 1
  • 6
  • 22
  • 1
    use kNilOptions for options instead of NSJSONReadingAllowFragments – Prince Agrawal Jan 30 '14 at 09:38
  • 1
    Why do you want to use `NSJSONReadingAllowFragments`? JSON seems to valid one. – Maciej Oczko Jan 30 '14 at 09:39
  • This is not valid JSON (if you wanted to return just a string in your JSON response, the correct JSON representation ) – iPatel Jan 30 '14 at 09:40
  • Can you give us some more information.. I have tried and it is working properly. – Rajesh Choudhary Jan 30 '14 at 09:41
  • @RajeshChoudhary The array "records" in that json response is having a number of values. So sometimes when i log this response its not printing as a whole reposne – LvN Jan 30 '14 at 09:45
  • what u need the ansewer – Anbu.Karthik Jan 30 '14 at 10:28
  • @Anbu.Karthik As i asked i want to retrieve the json data from server. The error i'm getting is only while parsing the json – LvN Jan 30 '14 at 10:41
  • its easy what are the key u want to retirve, means what the result u need – Anbu.Karthik Jan 30 '14 at 10:42
  • I want to store that records array into my app database. I know how to do that. My issue is the json dictionary object is getting error while executing. – LvN Jan 30 '14 at 10:50
  • 1
    Json result must start with Array – Vineesh TP May 17 '14 at 14:51
  • 1
    @VineeshTP - JSON most certainly need not start with an array. Either an array or an object is allowed. – Hot Licks Jun 09 '14 at 19:48
  • The error is probably occurring because the data is corrupted, possibly by unprintable characters ahead of the leading `{`. (Note, however, that an unprintable "byte order mark" is perfectly legit.) – Hot Licks Jun 09 '14 at 19:49
  • You could not possibly have gotten that message from that NSJSONSerialization invocation. – Hot Licks Jun 09 '14 at 19:50
  • For me this error occured because JSON was returned as string and started with " character. – Lukasz 'Severiaan' Grela Jun 20 '14 at 12:58
  • @Lukasz'Severiaan'Grela I am really curious at how you solve the " character problem from the Json response since I have the exact same issue. – S.H. Sep 19 '14 at 20:06
  • This question should be closed for two reasons: 1) The NSJSONSerialization invocation shown in the code specifies `NSJSONReadingAllowFragments` and would not have produced the message "option to allow fragments not set". The OP is not showing us the real code. 2) The problem is clearly due to "junk" in the data stream that does not display, and the OP needs to investigate what that is. We can only speculate. – Hot Licks Oct 16 '14 at 12:02

5 Answers5

10

I ran into the same error when consuming a feed from a php page. Just as you encountered, the resulting json string passed a visual inspection, but would fail to serialize. My suspicion was that there was a hidden character somewhere the feed, so I converted each character to its unicode decimal equivalent and examined the results:

NSString *feedStr = [[NSString alloc] initWithData:feedData encoding:NSUTF8StringEncoding];
for(int i=0; i<[feedStr length]; ++i)
{
    unichar c = [feedStr characterAtIndex:i];
    NSLog(@"decimal char %d", c);
}

I found that before the first character and after the last was the character #65279. After a quick google search I found What is this char? 65279, where this was identified as a byte order mark.

In my case, I was able to fix this at the source by opening and saving all included php files, using a text editor that provided an option to use the "Encode in UTF-8 without BOM" encoding. For more info on the php side, see How to avoid echoing character 65279 in php?

Community
  • 1
  • 1
Dave Burke
  • 119
  • 1
  • 3
  • NSJSONSerialization will handle a byte order mark, if it's not somehow corrupted. – Hot Licks Aug 13 '14 at 03:32
  • 1
    Why the -1? Editing the included php files using UTF-8 without BOM encoding clearly fixed the issue. Doing so stripped out any valid or corrupted BOM. This is still helpful to those wondering why their json, that passed visual inspection, isn't serializing; which was LvN's issue and is on point. Converting and logging each character to its unicode decimal equivalent will reveal any normally hidden characters that can be added by sub-par text editors. – Dave Burke Aug 13 '14 at 13:15
  • @HotLicks: At the beginning of the data, yes. That's the only place where a byte order mark should appear. There seems to be one at the end of the data as well, which is wrong. – gnasher729 Oct 16 '14 at 12:19
2

It usually is because of some warning message throwing out from your server without putting it in the response array. For example in PHP, some "warning messages" are not caught in your array so that when you finally use "echo json_encode($RESPONSE_ARR)," it is not a JSON format.

Exile3daime
  • 611
  • 6
  • 18
1

The JSON that you posted looks Ok. If that is what your iOS application received, it would get parsed. Even if it wasn't Ok, you wouldn't get this error message. JSON must start with '[' if it is an array, and '{' if it is a dictionary like yours, and everything else you get the error message that you got. So even if you sent '[934knsdf239][@@@' you wouldn't get this error message, because the data starts with the [ indicating an array.

You need to debug this in the iOS application. First convert the data to a string and print that and check it. If the string looks alright then print the data itself - sometimes people manage to add 0 bytes or control characters, or two byte order markers or something similar which are invisible in the string but are not legal JSON.

The option NSJSONReadingAllowFragments allows JSON that consists just of a string, number, boolean or null value. Don't use this unless you want to be able to process one of these on its own.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
0

I faced the same problem. But I found that the Url I was sending as a param to server was wrong. There was a little one character mistake. For example I was sending the below url

URL = https://somerUrl/api/v2/&venues/search?client_id=jkdasljf3242jka-fsdf-fadsfasd&lat=40.712488&long=-74.006277&distance=25

The mistake was extra & symbol in front of venues making trouble. So i removed & symbol and found worked for me. So, make sure you are sending the correct param to server.

Gurjinder Singh
  • 9,221
  • 1
  • 66
  • 58
0

The problem comes from response parsing. You are trying to de-serialize a JSON response (which MUST be contained in either an NSArray or NSDictionary) however your response is none of the above (Most likely a simple string).

You can try to Print out your server response. Please use the code in your catch block like. and identifying an error in server side or not.

Your server data is not proper JSON format then print out your server data and check a server data is valid or not.

URLSession.shared.dataTask(with: url) { (data, response, error) in

        if let jsonData = data {
            do {
                let parsedData = try JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as! [String: AnyObject]
            }
            catch let err{
                print("\n\n===========Error===========")
                print("Error Code: \(error!._code)")
                print("Error Messsage: \(error!.localizedDescription)")
                if let data = data, let str = String(data: data, encoding: String.Encoding.utf8){
                    print("Server Error: " + str)
                }
                debugPrint(error)
                print("===========================\n\n")

                debugPrint(err)
            }
        }
        else {
            debugPrint(error as Any)
        }

    }.resume()
AshvinGudaliya
  • 3,234
  • 19
  • 37