"JSON text must be an object or array" error - php

I'm using PHP to connect to an API and register some info using JSON and HTTP POST but it is not going well.
That is what I do:
I create a JSON object with the json_encode function:
$name = 'Mike';
$surname = 'Hans';
$fields = array('name' => json_encode($name), 'surname' => json_encode($surname));
$postData = json_encode($flds);
Once i have the post data, I just connect to the API with curl and login with oauth, but the API responde says:
JSON text must be an object or array (but found number, string, true,
false or null, use allow_nonref to allow this)
I have checked the allow_nonref in Google, but i could not find anything for PHP, all I have found is for Perl. Does anyone have any solution/advice to solve this?
Thanks!

You probably need to send the entire POST as JSON without nesting calls to json_encode, like this:
$fields = array('name' => $name, 'surname' => $surname);
$postData = json_encode( $fields);

To follow up on #nickb's answer, please only use one call to json_encode, it's far better at constructing valid json that you and I are, and it's more efficient to boot! (though we are entering the realm of micro-optimisation).
Have you tried taking the output of the json_encode and putting it into a validator/formatter such as the one here : http://jsonviewer.stack.hu/
Also, I think another likely problem could be the headers you are sending? The recieiving server could be strict and enforce that you use the correct 'Content-Type'. Are there any API docs avaliable?

Related

PHP : How to send data as a JSON object

I have build a simple PHP API system.
Now a partner company (* that isn't quite behaving as a partner *) and they are sending us data but since their system is making a lot of requests we need to debug.
The debug data they send us are the following:
But I have no clue might sound stupid but unfortunately yes. How to send this to our system as a JSON object.
Could anyone tell me how I can send this data as a JSON object so I can see how our system responds?
{"requested_info":"pers_code_live","provider_id":"20","provider_group_id":"4","indoor":false,"provider_location":"buiten","StartDate":"14-10-2016 16:00","EndDate":"22-10-2016 23:30","email":null,"lang":"nl","personal_code":"wehavediscount"}
Thanks in advance
EDIT
The info I receive is only readable by :
$JSonData = json_decode(file_get_contents('php://input'), true);
But I have no idea how to send the above mentioned data in a format that I have accept in the manner as described two lines up.
I can create a post variable with a JSON encoded array. That's no biggie. But the problem is the JSon object. I don't know how to send something as a JSon object and re-create their created situation.
The standard way is with json_encode():
$arr = ["first key" => 1, "second key" => "two", "third => [1,2,3]];
echo json_encode($arr);
Which will return
{"first key": 1, "second key": "two", "third": {1,2,3}}

Send request to api website and then api give me some data in array format, how to work with this data?

Send request to api website and then api give me some data in array format, how to work with this data ?
When I access to: example.com/api.php?name=papaya, it's will show
Array ( [0] => papaya [1] => fruit )
in my site, I want to work with this array data like
$url = "example.com/api.php?name=papaya ";
if ($url[1] == "fruit" )
{ echo "food"; }
How to do that?
You guys aren't understanding what the OP is asking. He's asking how he can use the data that is returned from the api request. I don't think he has access to the API itself but rather the end-point.
Now to answer the question.
Basically you'd need to either use cURL or something like file_get_contents().
For this example, I'm going to use file_get_contents() to give you a basic idea:
Now the below example will get the returned data from the geoplugin.net api.
$ip = $_SERVER['REMOTE_ADDR'];
$result = #json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip));
print_r($result);
?>
For your case, you'd do something similar:
<?php
$result = #json_decode(file_get_contents("example.com/api.php?name=papaya"));
// do what you need to with result...
echo $result[0];
?>
Obviously this isn't the best way to do it; as you'd need to make sure there were no errors (suppressed the errors with the # before the json_decode()).
Now I'm not going spoon feed you, so here are some examples on how to do some cURL requests.
PHP.NET cURL Examples
Simple PHP cURL Example
All examples of PHP cURL....
If you have control over the API, then set the response header Content-Type: application/json, then json_encode any output, and json_decode on the client side.
Otherwise theres not much you can do with that string.. possibly use a regex method to extract the key and values?

Using http_get php

While using a certain API to extract information the docs suggest that I need to pass a URL to retrieve data. The data is returned in XML, however to receive it in JSON format HTTP Accept header value of 'application/json' should be specified.
I am trying to achieve this in PHP, e.g. the URL to retrieve information is http://www.example.com?someContent which returns data in XML.
I am currently using http_get function from PHP, however, it doesn't seem to be working at all.
Any suggestions on how can I extract information and then also request it in JSON format.
The above link is invalid. This documentation exists at http_get
Untested, but this should work. Set the headers option to an array of headers you want to use.
$response = http_get("http://www.example.com/?someContent", array(
'headers' => array(
'Accept' => 'application/json'
)
), $info);
print_r($info);
http://php.net/manual/en/function.http-get.php
Try: $body = http_parse_message(http_get($url))->body; then you can use $body.
Alternatively, you can use cURL. Since the result is in JSON, you'll need to parse the XML then output as an array into the json_encode function.

Having trouble POSTing nested JSON using PHP

I'm trying to send some form data as a JSON object to a sample app on Force.com. I get the form data using jQuery and POST it to a PHP file on my server which then sends it to the sample app linked above. The response I get from the sample app however tells me that I'm making some mistakes along the way.
The PHP file that talks to the sample Force.com app:
<?php
$url = 'https://cmsamp.secure.force.com/GenericApp/services/apexrest/GenericApp';
$data = $_POST[ 'data'];
$options = array('http' => array('method' => 'POST','content' => http_build_query($data)));
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
echo $result;
?>
Client-side jQuery code that posts form data to the PHP file:
var sample_form_data = {"attributes":{"type":"Generic_App__c"},"Application_Type__c":"iPay","Return_Email__c":"lsmith#cmsrep.com","Name":"Bus Test","ACHRejectFee__c":"123456789","ApplicationDate__c":"2000-01-01","BusinessPhone__c":"(555) 123-4567","Email__c":"thetest#testemail.com","InternetPercentage2__c":"0","MailingState__c":"CA","MOTO7__c":"true","NumOfLocations__c":"15"};
$.post( url, { data: JSON.stringify( sample_form_data ) }, function( result ) {
console.log( result );
});
The response from I get from the Force.com app:
"No content to map to Object due to end of inputInsert failed.
First exception on row 0;
first error: REQUIRED_FIELD_MISSING,
Required fields are missing: [Name]: [Name]"
Desired "success" response:
"Success:
Generic App Object: Bus Test; was successfully created and inserted"
This is the output of var_dump($data) in the php code (line breaks added for readability:
string(405)
"{\"attributes\":
{\"type\":\"Generic_App__c\"},
\"Application_Type__c\":\"iPay\",
\"‌​Return_Email__c\":\"lsmith#cmsrep.com\",
\"Name\":\"Bus Test\",
\"ACHRejectFee__c\":\"123456789\",
\"ApplicationDate__c\":\"2000-01-01\",
\"B‌​usinessPhone__c\":\"(555) 123-4567\",
\"Email__c\":\"thetest#testemail.com\",
\"InternetPercentage2__c\":\"0\"‌​,
\"MailingState__c\":\"CA\",
\"MOTO7__c\":\"true\",
\"NumOfLocations__c\":\"15\"
}"
The generic app just expects to get a JSON object with the proper fields. When I submit the following through a REST client it works as intended (again, line breaks added for readability):
{"attributes":
{"type":"Generic_App__c"},
"Application_Type__c":"iPay",
"Return_Email‌​__c":"test#example.org",
"Name":"Bus Test",
"ACHRejectFee__c":"123456789",
"ApplicationDate__c":"2000-01-01",
"BusinessPho‌​ne__c":"(555) 123-4567",
"Email__c":"thetest#testemail.com",
"InternetPercentage2__c":"0",
"Mailing‌​State__c":"CA",
"MOTO7__c":"true",
"NumOfLocations__c":"15"}
Anyone have ideas on how to solve this?
From the looks of those var_dumps, I'd say you need to strip those slashes out of $data before you use it. Try stripslashes.
http_build_query also expects an array. Since your data is already a json string, I think you should probably omit it. You may need to url encode it, but you should just use the regular urlencode function for that.
Also, I'm not familiar with the php context mechanism you're using and I'm deeply unsatisfied with the php.net documentation, but I can't shake this nagging feeling that the 'content' => $data is doing something more than just setting the content. Do you have a good documentation link for the stream contexts actually using the 'content' option?

Don't pass OAuth in POST variables - PHP OAuth Pecl library

I am working with a third party service that requires me to authenticate through OAuth1 to make requests. I can successfully authenticate and get data back with most of their calls using GET, however some calls they require POST and this is where the problem lies. To authenticate I am using the below:
$oauth = new OAuth(MY_KEY,MY_SECRET);
$oauth->setNonce(rand());
$oauth->setToken('','');
Then for a GET call I am doing something like below:
$array = array(
'partnerId'=>'1234'
);
$call = $oauth->fetch("https://domain.co.uk/api/getInfo/",$array);
$data = $oauth->getLastResponse();
This all works perfectly, and I can print out the $data
However with POST calls:
$oauth = new OAuth(MY_KEY,MY_SECRET);
$oauth->setNonce(rand());
$oauth->setToken('','');
$oauth->enableDebug();
$oauth->setAuthType(OAUTH_AUTH_TYPE_AUTHORIZATION);
$array = array(
'rid' => "$restaurantId",
'datetime' => "$datetime",
'partysize' => $covers,
'timesecurityID' => "$securityId",
'resultskey' => "$resultskey"
);
$call = $oauth->fetch("https://domain.co.uk/api/booking/?pid=1234&st=0",$array,OAUTH_HTTP_METHOD_POST);
$data = $oauth->getLastResponse();
I keep getting the error: Invalid Consumer Signature
Speaking to their tech guy he suggested
Your sbs value indicates that you’re signing with all of the POST
parameters, whereas you only need to sign with the query string. In
this case it would be “pid=1234&st=0”. Unfortunately, I’m not
familiar with the PHP libs and don’t have any recommendations on how
to alter the behavior.
and also mentioned common previous problems with a PHP implementation are:
The PHP HTTP lib will drop the query string once the method is
changed from GET to POST.
The PHP oAuth lib will use the post data
to sign the request rather than the query string or maybe both.
If I dump out the headers I get:
[sbs] => POST&https%3A%2F%2Fdomain.co.uk%2Fapi%2Fbooking%2F&datetime%3D2013-02-21T10%253A30%253A00%26oauth_consumer_key%3DMySiteV3TT%26oauth_nonce%3D1213111151%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1360835965%26oauth_token%3D%26oauth_version%3D1.0%26partysize%3D2%26pid%3D1531%26resultskey%3DfoqgEnYK%25252bIzRd6BV3T8eGQ%25253d%25253d%26rid%3D31852%26st%3D0%26timesecurityID%3D349367809
[headers_sent] => POST /api/booking/?pid=1234&st=0 HTTP/1.1
It looks like it is sending the OAuth data with the rest of the post, I just want this sent in the Authorization header (which it is also sending)
Authorization: OAuth oauth_consumer_key="MySite",oauth_signature_method="HMAC-SHA1",oauth_nonce="1772854358",oauth_timestamp="1360768712",oauth_version="1.0",oauth_token="",oauth_signature="2%2B7xb%2BJ5cdbUDC5UHfsdfsNpFM1pE%3D"
So I think I need to strip the OAuth data from the post request but keep it as a Authorization Header but just can't find the magic way to do that!
I've seen this. In fetch(), try urlencoding your $array and passing it in as a string of the form:
rid=[restaurantId]&datetime=[datetime]&...
Also give the header (final parameter of fetch()):
Content-Type: application/x-www-form-urlencoded

Categories