Prakhar Prakash Bhardwaj
Prakhar Prakash Bhardwaj

Reputation: 1014

"JSON text did not start with array or object and option to allow fragments not set."

While making a POST request, Xcode debugger shows an error

Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

Here is the POST function,

 func startArchive() {

        let app_Id = (appId.base64Decoded()!)
        let job_Id = (jobId.base64Decoded()!)

        var response_ = 0

        guard let url = URL(string: "https://xxx.yyyy.com/question/abc") else {return}
        let request = NSMutableURLRequest(url:url)
        request.httpMethod = "POST"
        let postString = "session_id=\(pSessionId)&job_id=\(job_Id)&app_id=\(app_Id)&action=start"
        print(postString)
        request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.httpBody = postString.data(using: String.Encoding.utf8)

        let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
            guard error == nil && data != nil else {                                                          // check for fundamental networking error
                print("error=\(String(describing: error))")
                return
            }

            do {
                if let responseJSON = try JSONSerialization.jsonObject(with: data!) as? [String:AnyObject]{
                    print(responseJSON)
                    print(responseJSON["status"]!)                   
                    response_ = responseJSON["status"]! as! Int                    
                    print(response_)

                    //Check response from the sever
                    if response_ == 200
                    {
                        OperationQueue.main.addOperation {
                            print("Login Successful")
                        }                        
                    }                        
                    else
                    {
                        OperationQueue.main.addOperation {

                            print("Login Failed")

                        }                      
                    }
                }
            }
            catch {
                print("Error -> \(error)")
            }
        }
        task.resume()
    }

I have tried with header, but still, the same error appears.

request.setValue("text/html; charset=UTF-8", forHTTPHeaderField: "Content-Type")

Here is the PHP function for the above request,

public function abc(Request $request)
{        $session_id = !empty($request->input('session_id')) ? $request->input('session_id') : '';
    $action = $request->input('action');
    $archiveId = !empty($request->input('archive_id')) ? $request->input('archive_id') : '';

    $data = array();

    $opentok = new \OpenTok\OpenTok($_SERVER['TOKBOX_' . strtoupper($this->tenantName) . '_API_KEY'], $_SERVER['TOKBOX_' . strtoupper($this->tenantName) . '_SECRET']);

    if ($action == 'start') { // Start recording
        try {
            // Create an archive using custom options
            $archiveOptions = array(
                'name' => 'Important Presentation', // default: null
                'hasAudio' => true, // default: true
                'hasVideo' => true, // default: true
                'outputMode' => \OpenTok\OutputMode::COMPOSED  // default: OutputMode::COMPOSED
            );

            $archive = $opentok->startArchive($session_id, $archiveOptions);

            $job_id = $request->input('job_id');
            $app_id = $request->input('app_id');

            // check record exist or not
            $check_archive = DB::table('practice_question_recordings')
                ->where('job_id', $job_id)
                ->where('app_id', $app_id)
                ->get();

            if (empty($check_archive)) { // insert data
                $insert_data = array();
                $insert_data['job_id'] = $job_id;
                $insert_data['app_id'] = $app_id;
                $insert_data['archive_id'] = $archive->id;
                $insert_data['archive_url'] = '';

                DB::table('practice_question_recordings')->insert($insert_data);
            } else {  // Update data
                $update_data = array();
                $update_data['job_id'] = $job_id;
                $update_data['app_id'] = $app_id;
                $update_data['archive_id'] = $archive->id;
                $update_data['archive_url'] = '';

                DB::table('practice_question_recordings')
                    ->where('job_id', $job_id)
                    ->where('app_id', $app_id)
                    ->update($update_data);
            }

            $data['status'] = 200;
            $data['archive_id'] = $archive->id;
            $data['message'] = 'Recording started successfully.';
        } catch (Exception $ex) {

            $data['status'] = 500;
            $data['message'] = $ex->getMessage();
        }
    } else { // Stop recording
        try {
            $archive_detail = $opentok->stopArchive($archiveId);

            $data['status'] = 200;
            $data['archive_detail'] = $archive_detail;
            $data['message'] = 'Recording stopped successfully.';
        } catch (Exception $ex) {
            $data['status'] = 500;
            $data['message'] = $ex->getMessage();
        }
    }

    return response()->json($data);
}

Upvotes: 1

Views: 3957

Answers (1)

Prakhar Prakash Bhardwaj
Prakhar Prakash Bhardwaj

Reputation: 1014

So finally I was able to detect the issue. The issue was in the subdomain part of the URL.

https://first.yyyy.com/question/abc

Since I was using the session id of another sub-domain [OpenTok] and passing it as a parameter in this, Status code 500 appeared.

https://second.yyyy.com/question/abc

Also, I changed my POST function structure to this:

    func startArchive() {

    let app_Id = (appId.base64Decoded()!)
    let job_Id = (jobId.base64Decoded()!)

    let parameters: [String: Any] = ["session_id": pSessionId, "job_id":job_Id, "app_id":app_Id, "action":"start"]

    print("Parameter:\(parameters)")
    guard let url = URL(string: "https://first.yyyy.com/question/abc") else {return}

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("iOS", forHTTPHeaderField: "deviceType")
    guard let httpbody = try? JSONSerialization.data(withJSONObject: parameters, options:[]) else {return}
    request.httpBody = httpbody

    let session = URLSession.shared
    session.dataTask(with: request) {data, response, error  in
        if let response = response {
            print(response)
        }
        if let data = data{

            let mdata = String(data: data, encoding: .utf8)
            print("This is data: \(mdata!)")

            do{
                //                    print("\(String(data: data, encoding: .utf8) ?? "")")
                if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary {
                    DispatchQueue.main.async {
                        _archiveId = (json["archive_id"] as! String)
                        print(json)
                    }
                }
            } catch {
                print(error)
            }
        }
        }.resume()
}

It worked fine for me and returned the data in JSON.

Upvotes: 1

Related Questions