Parse a json reply from a jquery result in php - javascript

I have a simple search form which query an external server for result with jquery
$("#formsearch").on("submit", function (event) {
// everything looks good!
event.preventDefault();
submitFormSearch();
});
function submitFormSearch(){
// Initiate Variables With Form Content
var searchinput = $("#searchinput").val();
$.ajax({
type: "GET",
url: "https://external-server/api/",
headers: {"Authorization": "xxxxxxxxxxxxxx"},
data: "action=Search&query="+searchinput,
success:function(json){
console.log(json);
$.ajax({
type: "POST",
url:'search_func.php',
data: "func=parse&json="+json,
success:function(data) {
console.log(data);
$('#risultato_ricerca').html(data);
}
});
}
});
}
The first GET ajax works properly and I get correct data but trying to send this json data to my php script in post I can't get data.
This is the code in search_func.php
if(isset($_POST['func']) && !empty($_POST['func'])){
switch($_POST['func']){
case 'parse':
parse($_POST['json']);
break;
default:
break;
}
}
function parse($json) {
$obj = json_decode($json,true);
var_dump($obj);
}
... it displays NULL
Where I'm wrong ?
EDIT:
SOLVED
changing:
data: "func=parse&json="+json,
to:
data: { func: 'parse', json: JSON.stringify(json) },
json code is correctly passed to search_func.php
Changed function parse in php file to:
function parse($json) {
$data = json_decode(stripslashes($json),true);
print_r($data);
}
Thank you.

Is the javascript json variable correctly filled (i.e. what does your console show you?) Possible you must encode the json variable to a string before posting.
i.e: instead of data: "func=parse&json="+json, use data: "func=parse&json="+JSON.stringify(json),

See this: http://api.jquery.com/jquery.ajax/
The correct syntax is: data: { func: 'parse', json: my_json_here }
If this doesn't works is probably that you have to encode the JSON to a string (see JSON.stringify())

Related

Ajax sends two empty arrays and one filled, PHP receives only the full one

I'm completely new to PHP. Working with ajax, php and WordPress I'm sending an object with ajax:
let import_data = {
action: 'import_data',
data: {
first_array: [], // this one is empty
second_array: [], // this one too
third_array: [1,2,3] // this one is full
}
};
I've checked the import_data object many times right before it was sent. The php, however, always receives:
import_data = {
action: 'import_data',
data: {
third_array: [1,2,3]
}
}
The question is why is that happening and how can I achieve receiving all arrays, whether they are empty or not, i.e.
import_data = {
action: 'import_data',
data: {
first_array: [],
second_array: [],
third_array: [1,2,3]
}
}
I need to refactor a lot of code now due to this issue so I'm trying to solve it as easy as possible, but if there is a common known right way to deal with it I'll use it. Thanks in advance!
P.S. In case you wondering, yes, if all arrays being sent are full, php will receive all of them.
UPD In the comments I got I might've wanted to add contentType or json.strngify my data. It didn't help, but I might do it wrong, so I'll try to partly show my code below:
var import_data = {
action: 'start_import',
sliced_batch: {
rows_to_add: [],
rows_to_delete: [],
rows_to_update: [1,2,3,4,5,...]
}
};
function ajax_call(import_data) {
// ... processes
jQuery.ajax({
url: start_import_ajax.url, // url from php file
type: 'POST',
contentType: "text; charset=utf-8", // sending string with cyrillic (ukrainian lng)
dataType: 'application/json', // want to recieve json
data: JSON.stringify(import_data),
success: function(response) {
// ... processes import_data ...
if(it is the end of data) return;
else ajax_call(import_data);
},
error: function(e) {
// here is where I end up
}
}
PHP side is now pretty shy, as I just made a pause and wanted to see my data in console:
function start_import_callback() {
echo json_decode($_POST);
echo $_POST;
echo json_decode($_POST['sliced_batch']);
echo $_POST['sliced_batch'];
wp_die();
}
I've tried all echo's one by one, but always saw:
{
"readyState": 4,
"responseText": "0",
"status": 400,
"statusText": "error"
}
When NOT stringifying and NOT specifying contentType/dataType it returns:
{
action: 'import_data',
sliced_batch: {
rows_to_update:
{
"ID": "00000006125",
"CatalogueNumber": "bla, bla",
"Category": "bla, bla",
"Manufacturer": "bla",
"Nomenclature": "blablablablabla",
"NomenclatureUkrainian": "bla",
"StockStatus": "instock",
"Price": "2 315",
"Parent": "blabla",
"Sorting": "99"
},
{},...
]
}
}
So, rows_to_delete: [] and rows_to_add: [] are missing...
You are using jQuery dataType options wrong!
The dataType: value should be 'json' not 'application/json' because your value will request with HTTP accept: */* but if you use 'json' it will be accept: application/json.
Option 1
Use content type application/json.
The contentType: should be 'application/json' or 'application/json;charset=utf-8'.
By this content type you will be now able to receive POST data in JSON but you cannot access them with $_POST because the data is not valid application/x-www-form-urlencoded.
Full code for client side:
var import_data = {
action: 'start_import',
sliced_batch: {
rows_to_add: [],
rows_to_delete: [],
rows_to_update: [1,2,3,4,5]
}
};
function ajax_call(import_data) {
// ... processes
jQuery.ajax({
url: 'test.php', // url from php file
type: 'POST',
contentType: "application/json;charset=utf-8", // sending string with cyrillic (ukrainian lng)
dataType: 'json', // want to recieve json
data: JSON.stringify(import_data),
success: function(response) {
// ... processes import_data ...
},
error: function(e) {
// here is where I end up
}
});
}
Code for PHP:
$data = json_decode(file_get_contents('php://input'), true);
// use $data['sliced_batch'] to access `rows_to_add`, `rows_to_delete` etc.
Option 2
Use content type application/x-www-form-urlencoded.
With this content type, you will be able to access $_POST properly.
However, to use this request content type in header, the jQuery itself will be modify the value if it is empty jQuery will be just delete it!! So, you need to JSON string only sliced_batch property.
Here is the JS code:
var import_data = {
action: 'start_import',
sliced_batch: {
rows_to_add: [],
rows_to_delete: [],
rows_to_update: [1,2,3,4,5]
}
};
function ajax_call(import_data) {
// ... processes
// modify `sliced_batch` property to be JSON string to prevent jQuery remove empty properties.
import_data.sliced_batch = JSON.stringify(import_data.sliced_batch);
jQuery.ajax({
url: 'test.php', // url from php file
type: 'POST',
// just remove contentType option. It is no need.
//contentType: "application/json;charset=utf-8", // sending string with cyrillic (ukrainian lng)
dataType: 'json', // want to recieve json
data: import_data,
success: function(response) {
// ... processes import_data ...
},
error: function(e) {
// here is where I end up
}
});
}
PHP:
$sliced_batch = ($_POST['sliced_batch'] ?? '');
$sliced_batch = json_decode($sliced_batch, true);
// you can now access $sliced_batch['rows_to_add'], etc...
So, thanks once again to #vee for his explanation, but here's one more thing I'd like to share as it was crucial to get everything to work.
First, for json_decode method the JS object keys should be double-quoted, i.e. NOT
$bad_json = '{ bar: "baz" }';
json_decode($bad_json); // null
or
$bad_json = '{ 'bar': "baz" }';
json_decode($bad_json); // null
BUT
$bad_json = '{ "bar": "baz" }';
json_decode($bad_json); // array("bar" => "baz")
Second and most important!
When dealing with WordPress it sets its own rules and shows focuses!
Depending on what answer you'd like to get, you may want to use function wp_unslash(). Looking at the stringified data in console I saw somth like this:
"\u0421\u0435\u0440\u0432\u0435\u0440: \u0424\u0430\u0439\u043b\u0456\u0432 av_imp_p_WEB.csv \u0456 av_imp_p_WEB_previous.csv \u043d\u0435 \u0431\u0443\u043b\u043e \u0432\u0438\u044f\u0432\u043b\u0435\u043d\u043e. \u041f\u043e\u0447\u0438\u043d\u0430\u044e \u0456\u043c\u043f\u043e\u0440\u0442 \u0432\u0441\u044c\u043e\u0433\u043e
// it is more common for contentType: "application/x-www-form-urlencoded"
It is the dirty work of WooCommerce (as I read from another's people opinion) and it hinders parsing it the right way, so my full code is:
JS
var import_data = {
"action": "start_import",
"sliced_batch": {
"rows_to_add": my_data1,
"rows_to_delete": my_data2,
"rows_to_update": my_data3
}
};
function ajax_call(import_data) {
// ... processes
jQuery.ajax({ // ajax to php to save the file to uploads and move it to the plugin's folder
url: start_import_ajax.url, // url from php file
type: 'POST',
//contentType: "application/json;charset=utf-8", // what you send
dataType: 'JSON', // what you would like as a response
data: {
"action": import_data.action,
"sliced_batch": JSON.stringify(import_data.sliced_batch)
},
success: function(response) {
//response = JSON.parse(response); // if you'd like to console.log what you've sent
console.log(response);
}
....
PHP
$sliced_batch = wp_unslash($_POST['sliced_batch']);
$sliced_batch = json_decode($sliced_batch, true);
$result = start_import($sliced_batch);
if($result == 0) {
echo json_encode(["status" => 0]);
} else echo json_encode(["status" => 1]);

POST request in JSON using $.ajax()

My backend API accepts data in JSON format, such as:
{ "article_id" = 1 }
In the front-end, I tried to add the following javascript to a button:
function articleIsSelected(id) {
let data = '{"article_id":' + id + '}';
$.ajax({
url:"https://www.myurl.com",
data: data,
type: "post",
contentType: "application/json",
success: function () {
alert("Selection succeeded!");
},
error: function () {
alert("Selection failed.");
},
});
}
It returns that the request was successful, but my database is not updated. There is something wrong with the data format. Instead of trying to hard code the data in JSON format, one should sign the value to "article_id" and then JSON encode it with JSON.stringify(data).
The data is not proper JSON, change it to:
let data = {"article_id": id};
And make sure you encode it:
JSON.stringify(data)

Why we use data.d while get response from ajax json call?

I am using AJAX call from my Html page to call a method from my asmx.cs file, using below code:
<script type="text/javascript">
function ajaxCall() {
var UserName = $("#<%=lblUsername.ClientID %>").text();
$("#passwordAvailable").show();
$.ajax({
type: "POST",
url: 'webServiceDemo.asmx/CheckOldPassword',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ UserName: UserName }),
success: function (data) {
if (JSON.parse(data.d) != "success") // Why we need to use "data.d" ??
{
$("#passwordAvailable").attr("src", "App_Themes/NewTheme/images/deleteICN.gif");
$("#<%=txtOldPwd.ClientID %>").css({ 'border': '1px solid red' });
}
else {
$("#passwordAvailable").attr("src", "App_Themes/NewTheme/images/signoff.gif");
}
}
});
}
</script>
So my Question is why do we need to use data.d ? Why does all data is being stored in .d and what is .d?
Because when I use only data it's not giving me correct return values but when I used data.d it does.
please give me suggestions.
Server side code C#
[WebMethod]
public string CheckOldPassword(string UserName)
{
// code here
string sRtnValue = "success";
return sRtnValue;
}
so d is not property or variable but still I got value in .d
Thanks
C# 3.5 and above will serialize all JSON responses into a variable d.
When the server sends a JSON response it will have a signature similar to this:
{
"d" : {
"variable" : "value"
}
}
With a console.log(data) inside the ajax success function you'll see the responses data structure in the browser console.

Form post warning message after upgrading jquery

I have upgraded to jquery 1.10.2. I am using jquery migrate and I am having the warning message "jQuery.parseJSON requires a valid JSON string"
I have not understood how I can correct that. Can anyone help me out with the best solution of how I can remove the warning message
The javascript is as follows:
function Search() {
$.ajax({
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "html",
url: "#Url.Action("Search")",
data: JSON.stringify({myModel: $("#DateFrom").val()}),
success: function (data)
{
$("#NewDiv").html(data);
},
error: function (request, status, error)
{
DisplayError(ParseErrorFromResponse(request.responseText, "Unknown error"), true);
}
});
}
In the Controller:
public PartialViewResult Search(myModel myModel)
{
return PartialView("SearchResult", myModel);
}
ParseErrorFromResponse:
Function ParseErrorFromResponse(responseText, defaultError)
{
var text = responseText.replace("<title>", "TitleStart");
var startIndex = text.indexOf("TitleStart");
var endIndex = text.indexOf("TitleEnd");
return (startIndex == -1 || endIndex == -1) ? defaultError : text.substring(startIndex + 10, endIndex);
}
You need to send your data as JSON.
Where you have data: $("#DateFrom").val(), replace it with data: JSON.stringify({$("#DateFrom").val()}).
EDIT: You may need to send it as JSON.stringify({(myModel: $("#DateFrom").val()}).
The error may be related to "" or false values that used to convert to null in versions of jQuery prior to 1.9.0 per THIS PAGE
Here it the relevant excerpt including the suggested solution:
JQMIGRATE: jQuery.parseJSON requires a valid JSON string
Cause: Before jQuery 1.9.0, the $.parseJSON() method allowed some
invalid JSON strings and returned null as a result without throwing an
error. This put it at odds with the JSON.parse() method. The two
methods are aligned as of 1.9.0 and values such as an empty string are
properly not considered valid by $.parseJSON().
Solution: If you want to consider values such as "" or false
successful and treat them as null, check for them before calling
$.parseJSON(). Since falsy values such as an empty string were
previously returned as a null without complaint, this code will
suffice in most cases:
var json = $.parseJSON(jsonString || "null");
If your own code is not
calling $.parseJSON() directly, it is probably using AJAX to retrieve
a JSON value from a server that is returning an empty string in the
content body rather than a valid JSON response such as null or {}. If
it isn't possible to correct the invalid JSON in the server response,
you can retrieve the response as text:
$.ajax({
url: "...",
dataType: "text",
success: function( text ) {
var json = text? $.parseJSON(text) : null;
...
}
});
Remove content-type attribute and do like this:
function Search() {
$.ajax({
cache: false,
url: "#Url.Action("Search","ControllerName")",
dataType:"html",
data:
{
myModel: $("#DateFrom").val()
},
success: function (data)
{
$("#NewDiv").html(data);
},
error: function (request, status, error)
{
DisplayError(ParseErrorFromResponse(request.responseText, "Unknown error"), true);
}
});
}
and in action:
public PartialViewResult Search(string myModel)
{
return PartialView("SearchResult", myModel);
}
I think it's because you're missing double quotes around key myModel in line
...
data: JSON.stringify({myModel: $("#DateFrom").val()},
...
and not because of jquery version upgrade.try using
data: JSON.stringify({"myModel": $("#DateFrom").val()},
Try like this.. You have to return Json as result from your Search().
public JsonResult Search(myModel myModel)
{
return Json(result);
}
and also in you Script, try like this..
$.ajax({
type:"POST"
cache: false,
contentType: "application/json; charset=utf-8",
url: "#Url.Action("Search","ControllerName")",
dataType: "json",
data: JSON.stringify({"myModel": $("#DateFrom").val()}),
success: function (data)
{
$("#NewDiv").html(data);
}
});
Also check $("#DateFrom").val() is having correct value and put an
alert(data)
in success and check the returned data.
I have updated the url.

JQuery Ajax not sending data to PHP

myscript.js below is outputing:
[{"orcamento":"10","atual":"20","desvio":"","data":"2015-01-01","nome_conta":"BBB","nome_categoria":"abc","nome_entidade":"def"}]
myscript.js:
if (addList.length) {
$.ajax($.extend({}, ajaxObj, {
data: { "addList": JSON.stringify(addList) },
success: function (rows) {
$grid.pqGrid("commit", { type: 'add', rows: rows });
},
complete: function () {
$grid.pqGrid("hideLoading");
$grid.pqGrid("rollback", { type: 'add' });
$('#consola').text(JSON.stringify(addList));
}
}));
}
The JSON data above has to be sent to my script.php below:
if( isset($_POST["addList"]))
{
$addList = json_decode($_POST["addList"], true);
var_dump ($addList);
echo "test";
exit();
}
Although the data is correct and myscript.php is being called it isn't returning anything. I get:
NULLtest
I tried using GET, instead of POST but the result is the same, what is wrong with the code above?
EDIT:
Here's the ajaxObj used in the ajax request:
var ajaxObj = {
dataType: "json",
url:"../myscript.php",
type: "POST",
async: true,
beforeSend: function (jqXHR, settings) {
$grid.pqGrid("showLoading");
}
};
From the PHP Docs on json_decode:
NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
So it is most likely that there is some error in your JSON data that is preventing json_decode from parsing it correctly, I've ran that snippet through jsonlint and it does say that it's valid JSON, but it's worth checking a larger sample of the data you send to the server for inconsistencies.
Other than that, is there any reason that you are calling JSON.stringify on the data object prior to sending to the server? I would try just sending the object itself as the data parameter of your AJAX call like so:
$.ajax($.extend({}, ajaxObj, {
data: { "addList": addList },
success: function (rows) {
$grid.pqGrid("commit", { type: 'add', rows: rows });
},
complete: function () {
$grid.pqGrid("hideLoading");
$grid.pqGrid("rollback", { type: 'add' });
$('#consola').text(JSON.stringify(addList));
}
}));
And see if that helps:
EDIT
I should have noticed in my original answer, you will not need to call json_decode on your posted data, jQuery encodes the data as post parameters correctly for you; It should be accessible within your PHP script as an associative array, try replacing your current var_dump statement in your PHP var_dump($_POST['addList'][0]['orcamento']); and you should be good to go.
First of all, be sure you are posting to a php file, use firebug or similar tools to track your script..
I don't see the part you defined the target PHP file on your javascript file..
A regular javascript code can look like this :
jQuery.ajax({
type : "post",
dataType : "json",
url : 'target.php',
data : {foo:bar },
success: function(response) {
// do something with response...
}
});
If you see that you are posting to the right php file the right parameters on firebug, try to use $_REQUEST if $_POST not working..
Firebug will show you the response of PHP file.. so do a print_r($_REQUEST['addList']) to see what is going on...

Categories