javascript strange comparison of strings [duplicate] - javascript

This question already has answers here:
Which equals operator (== vs ===) should be used in JavaScript comparisons?
(48 answers)
Difference between == and === in JavaScript [duplicate]
(2 answers)
Closed 8 years ago.
I have an ajax function that sends an email to somewhere and receives a response from the server from a json object with type = either success or error
$("#submit_btn").click(function(event) {
event.preventDefault();
var post_data = {
'email': $("#email").val()
};
$.post( "sendEmail.php", post_data ).done(function(response){
if(response.type == 'success'){
$("#sentmail").fadeIn("slow")
setTimeout(function(){
$("#mail").val("Enter your email here");
$("#sentmail").fadeOut("slow")
},3000);
}
else{
$("#sentmailfail").fadeIn("slow")
setTimeout(function(){
$("#mail").val("Enter your email here");
$("#sentmailfail").fadeOut("slow")
},3000);
}
},"json")
});
The interesting part is that if I console.log(response) I get for instance {"type":"success","desc":"something"} and then straight after that console.log( (response.type == "error") ) // TRUE
if I take the consoled log from response and assign it to a variable for instance a = {"type":"success","desc":"something"} then a.type == "error" is false.
Can someone explain this?

If the output of console.log(response) is
{"type":"success","desc":"something"}
then response is most likely still a string (containing JSON), and strings don't have a type property:
> "foo".type == "error" // `undefined` is never equal to a string
false
Objects usually look differently in the console:
> console.log({"type":"success","desc":"something"})
Object {type: "success", desc: "something"} // in Chrome and Firefox at least
Solution: Parse the string first:
response = JSON.parse(response);
Related to jQuery:
I noticed that you intend to let jQuery parse the JSON for you, but you are passing "json" to the wrong function. You have to pass it to $.post(...), not to .done(...):
$.post("sendEmail.php", post_data, "json").done(...);
// instead of
// $.post("sendEmail.php", post_data).done(..., "json");
Then you don't need to parse it manually.
Related: Parse JSON in JavaScript?

Related

Trying to make a robloxsearch command with RBLX Api

I am trying to use ROBLOX's API to make a ;rs command but it isn't going so well.
Using request-promise I tried searching and it brought me this error:
SyntaxError: Unexpected token o in JSON at position 1
I have reviewed questions on here before and answered some. If this helps, I am using discord.js-commando for my command handler.
Here is the part the error is coming from:
let editMsg = await msgObject.reply(
":triumph: Finding ROBLOX Account, give me a second!"
);
let rs = await request({
uri: `https://users.roblox.com/v1/users/search?keyword=${idk}&limit=10`,
simple: false,
json: true
});
if (rs.userFacingMessage == "Something went wrong"){
if(rs.code == 5){
editMsg.edit("Sorry 😣, We couldn't process your search! The username you provided has been filtered!");
}
if(rs.code == 6){
editMsg.edit("Sorry 😣, We couldn't process your search! The username you provided is too short!");
}
}else {
let user = JSON.parse(rs)
msgObject.reply(user)
}
Here is a PasteBin link if you need to see the whole run() method.
request-promise with the option json: true automatically parses the JSON string in the response. It means your variable rs is already an object, not a JSON string.
The JSON.parse() method parses a JSON string, so when you try to parse an object, Node.js converts it to a string first ([object Object]). The first character is [ which is valid JSON, but the second one (the letter o) is not, so you receive a SyntaxError: Unexpected token o in JSON at position 1.
Try it out below:
const rs = {
previousPageCursor: null
}
try {
console.log(JSON.parse(rs))
} catch (error) {
console.log(error.message)
}
The API endpoint at https://users.roblox.com/v1/users/search?keyword=${idk}&limit=10 returns an object, so you can't simply send it as-is in a reply. You can use JSON.stringify() to create a string from that object, or you can get an array of users from rs.data.
If you want to return a single user, you can either grab the first item (rs.data[0]) from that array, or use the find() method to find one that matches your keyword:
} else {
const user = rs.data[0]
msgObject.reply(`\`\`\`${JSON.stringify(user, null, 2)}\`\`\``)
}
} else {
const user = rs.data.find((u) => u.name === idk)
msgObject.reply(`\`\`\`${JSON.stringify(user, null, 2)}\`\`\``)
}
PS: Next time when you don't want to be rude, don't write "Not trying to be rude but I want an answer [...]"

Get first word of string inside array - from return REST

I try get the sessionid before REST function, but in the case if I does not convert toString(); show only numbers (21 22 2e ...).
See this image:
1º:
Obs.: Before using split.
!!xxxxxxx.xxxxx.xxxxxxx.rest.schema.xxxxResp {error: null, sessionID: qdaxxxxxxxxxxxxxj}
My code:
var Client = require('./lib/node-rest-client').Client;
var client = new Client();
var dataLogin = {
data: { "userName":"xxxxxxxx","password":"xxxxxxxx","platform":"xxxxx" },
headers: { "Content-Type": "application/json" }
};
client.registerMethod("postMethod", "xxxxxxxxxxx/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
// parsed response body as js object
// console.log(data); all return, image 1
// raw response
if(Buffer.isBuffer(data)){
data = data.toString('utf8'); // if i does not convert to string, return numbers, see image 1..
console.log(data); //all inside image 2, and i want just value from sessionid
var output = data;
var res = output.split(" "); // using split
res = res[4].split("}", 1);
}
console.log(res); //image 3
});
I tested with JSON.parse and JSON.stringify and it did not work, show just 'undefined' for all. After convert toString();, And since I've turned the values ​​into string, I thought of using split to get only the value of sessionid.
And when I used split, all transform to array and the return is from console.log(data), see image 2:
2º:
Obs.: After use split and convert to array automatically.
And the return after use split is with the conditions inside my code:
3º:
And the return after use split is with the conditions inside my code:
[ 'bkkRQxxxxxxxxxxxxx' ]
And I want just:
bkkRQxxxxxxxxxxxxx
I would like to know how to solve this after all these temptations, but if you have another way of getting the sessionid, I'd be happy to know.
Thanks advance!
After converting the Buffer to a string, remove anything attached to the front with using data.substr(data.indexOf('{')), then JSON.parse() the rest. Then you can just use the object to get the sessionID.
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
data = data.substr(data.indexOf('{'));
obj = JSON.parse(data);
console.log(obj.sessionID);
}
EDIT:
The issue you are having with JSON.parse() is because what is being returned is not actually JSON. The JSON spec requires the properties to be quoted ("). See this article
If the string looked like this, it would work: {"error": null, "sessionID": qdaxxxxxxxxxxxxxj}
Because the json is not really json, you can use a regular expression to get the info you want. This should get it for you.
re = /(sessionID: )([^,}]*)/g;
match = re.exec(data);
console.log(match[2]);
EDIT 2: After fully reading the article that I linked above (oops haha), this is a more preferable way to deal with unquoted JSON.
var crappyJSON = '{ somePropertyWithoutQuotes: "theValue!" }';
var fixedJSON = crappyJSON.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');
var aNiceObject = JSON.parse(fixedJSON);

Convert a SQL BIT into JSON through to jQuery and finally display in HTML?

I'm working with checkboxes and JSON and I'm trying to find the cleanest way to set a checkbox on a JSON return. The JSON pulls from a BIT field out of SQL, and the code below works but I don't really like it...
PHP:
$outputArray = array(
'submissionaddress' => htmlentities($row['StateSubmissionAddress'], ENT_COMPAT, 'UTF-8'),
'isactive' => $row['IsActive']);
return json_encode($outputArray);
JSON:
{"submissionaddress":"Temp","isactive":"1"}
jQuery:
success: function(data) {
var checked = (parseInt(data.isactive, 10) === 1) ? true : false;
$('#submissionAddressCheckBox').attr('checked', checked);
}
Javascript didn't like (data.isactive) and that always returned false, so I parsed it to an int. I assume that's because JSON returns "isactive":"1" and it's interpreted as a string.
What's the best way to interpret a BIT value into JSON, and than transfer that value into a checkbox in HTML?
You can convert the string to an int with + and then the !! converts to a boolean.
success: function(data) {
var checked = !!+data.isactive;
$('#submissionAddressCheckBox').attr('checked', checked);
}
Does your Ajax request has dataType set to json? If not you should parse it.

Replace one string with another using Angular.js or JavaScript [duplicate]

This question already has answers here:
Rename the property names and change the values of multiple objects
(3 answers)
Closed 7 years ago.
I have some JSON data and I need to replace one value with another string using Angular.js or JavaScript. My code is below:
$http({
method:'POST',
url:"php/getFilterCodeData.php",
data:filterData,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function successCallback(response){
console.log('filter',response.data);
$scope.last=[];
for(var i=0;i<response.data.length;i++){
$scope.arrCode=response.data[i].generated_code.split(',');
}
//console.log('arr',$scope.arrCode);
for(var i=0;i<$scope.arrCode.length;i++){
$scope.last.push($scope.arrCode[i].split("_").pop());
}
//console.log('last',$scope.last);
var newStr=$scope.last[0]+"-"+$scope.last[$scope.last.length-1];
//console.log('new str',newStr);
},function errorCallback(response) {
})
Here I am getting the below data using console:
filter [{
customer_name: "Big-Bazar"
expired_date: "23-12-2015"
generated_code: "medilink_global_01,medilink_global_02,medilink_global_03,medilink_global_04,medilink_global_05,medilink_global_06,medilink_global_07,medilink_global_08,medilink_global_09,medilink_global_10,medilink_global_11,medilink_global_12,medilink_global_13,medilink_global_14,medilink_global_15,medilink_global_16,medilink_global_17,medilink_global_18,medilink_global_19,medilink_global_20,medilink_global_21,medilink_global_22,medilink_global_23,medilink_global_24,medilink_global_25,medilink_global_26,medilink_global_27,medilink_global_28,medilink_global_29,medilink_global_30,medilink_global_31,medilink_global_32,medilink_global_33,medilink_global_34,medilink_global_35,medilink_global_36,medilink_global_37,medilink_global_38,medilink_global_39,medilink_global_40"
no_of_voucher: "40"
status: "generated"
voucher_amount: "3000"
voucher_code_id: "13"}]
Here I need to replace the generated_code: value with newStr. The expected output should be:
generated_code:01-40
In the Javascript:
$scope.filter = filter;
$scope.filter[0].generate_code = newStr;
To show the string, just use {{ filter[0].generate_code }} in your template.
AngularJS always watches changes to variables in the scope and will replace them in the template as they change, so it's pretty straight forward.
you do it like this:
response.data[i].generated_code=newStr;

Properly returning a JSON object with an embedded JS function

Updated Post
I have a solution for that problem which works with me so far (only tested on Firefox).
My main goal was to dynamically update a Flot graph with Ajax. I also need to dynamically update the axis styles and you can do this by the tickFormatter option. To avoid the problems I previously had, I simply insert the desired return string in the PHP array and JSON encode that array. After returned to the Ajax function I create a new function using the javascript Function() constructor (Link). I hope this helps someone.
Ajax
$.ajax({
url: 'someControllerWhichCreatesJSONdata',
data: 'some Value',
type: 'post',
cache: false,
datatype: 'json'
})
.success(function(data) {
var datas = data[0]; // fetch data array
var options = data[1]; // fetch options array
var xReturn = options.xaxes[0].tickFormatter; // fetch return string
var yReturn = options.yaxes[0].tickFormatter;
var xFunc = new Function("val", "axis", xReturn); // create function
var yFunc = new Function("val", "axis", yReturn);
options.xaxes[0].tickFormatter = xFunc; // update tickFormatter with function
options.yaxes[0].tickFormatter = yFunc;
$.plot($("#yw0"), datas, options);
})
.error(function(data) {
$("#error").html(data.responseText); // show error in separate div
});
PHP array
$options = array(
'legend' => array(
'position' => 'nw',
'show' => true,
'margin' => 10,
'backgroundOpacity' => 0.5
),
'grid' => array(
'clickable' => true,
'hoverable' => true
),
'pan' => array('interactive' => true),
'zoom' => array('interactive' => true),
'axisLabels' => array('show' => true),
'xaxes' => array(
array(
'axisLabel' => 'someUnit',
'tickFormatter' => 'return "foo bar"' // enter whatever return value you need
)
),
'yaxes' => array(
array(
'axisLabel' => 'someUnit',
'tickFormatter' => 'return "foo bar"'
)
)
);
I skip the data array as it looks similar. Both arrays get combined and JSON encoded.
public function actionSomeControllerWhichCreatesJSONdata() {
$returnArray = array($data, $options);
echo json_encode($returnArray);
return true;
}
The resulting array looks like the one I've posted in the bottom of this post.
Original Post
I'm trying for hours now, but I can't get this to work.
I have an Ajax request which gets a JSON object as return value on success. This works fine as long as I don't use a JS function in my JSON array. So my JSON array looks as follows (after json_encode):
[{
"data": [{
{1,2},
{3,4},
}],
"function": "function(){return \"foo bar\";}"
}]
In order to get rid of the "'s in the function string. I use str_replace and replace the quoted string with an unquoted one. This then looks like so:
[{
"data": [{
{1,2},
{3,4},
}],
"function": function(){return "foo bar";}
}]
The plain json_encode works fine and my Ajax function reads it as a JSON object. After I replace the string it turns out that the return value is no longer a JSON object but a plain text string. I've tried to parse the string again with jquery.parseJSON() but this results in the syntax error:
SyntaxError: JSON.parse: unexpected keyword at line 1 column 396 of the JSON data
Ajax function:
$.ajax({
url: 'someControllerWhichCreatesJSONdata',
data: 'some Value',
type: 'post',
cache: false,
datatype: 'json' // or text when trying to parse
})
.success(function(data) {
console.log(data);
var dat = jQuery.parseJSON(data); // trying to parse (only when dataType: "text")
var datas = dat[0]; // or data[0] when datType = json
var options = dat[1]; // ---
$.plot($("#yw0"), datas, options); // trying to update a FLOT window
})
.error(function(data) {
console.log("error");
$("#error").html(data.responseText); // show error in separate div
});
So when using this function and setting the return type to "json", it produces an error. If the return type is "text" and I try to parse the string I get the error above. Is there any solution for this problem or am I doing something completely wrong?
Thank's for your help!
UPDATE
Sorry of course my JSON data is not valid! As I said, my JSON object gets created by json_encode which I guess should get the syntax right. The plain array after son_encode looks like:
[[{
"data":[[0.0042612,0.0042612]],
"label":"WISE.W3: Cutri et. al 2012",
"lines":{"show":false},
"points":{"show":true,"radius":3}}],
{
"legend": {
"position":"nw",
"show":true,
"margin":10,
"backgroundOpacity":0.5},
"grid": {
"clickable":true,
"hoverable":true},
"pan":{"interactive":true},
"zoom":{"interactive":true},
"axisLabels":{"show":true},
"axisLabel": {
"unit":"Jy",
"id":null,
"name":null},
"tickFormatter":"$tickFormatter$",
"position":"right"
}]
and after str_replace I get
[[{
"data":[[0.0042612,0.0042612]],
"label":"WISE.W3: Cutri et. al 2012",
"lines":{"show":false},
"points":{"show":true,"radius":3}}],
{
"legend": {
"position":"nw",
"show":true,
"margin":10,
"backgroundOpacity":0.5},
"grid":{"clickable":true,"hoverable":true},
"pan":{"interactive":true},
"zoom":{"interactive":true},
"axisLabels":{"show":true},
"axisLabel":{"unit":"Jy","id":null,"name":null},
"tickFormatter":function(val, axis){return val.toExponential(2)},
"position":"right"
}]
Adeno pointed it out already, your JSON syntax is not valid.
Please try to validate your JSON with a linter, like http://jsonformatter.curiousconcept.com/
This is a bit better:
[{"data":[["1","2"],["3","4"]],"function":"function(){return \"foo bar\";}"}]
And the other thing is: you should not manually deserialize the JSON. All newer versions of jQuery will automatically deserialize JSON based on the response's content-type header.
You already set dataType to json for the ajax request.
The response is JSON and will be de-serialized.
So you can directly use
.success: function(response) {
console.log(response.data);
console.log(response.function);
}
Answer for the questions/issue from the comments:
Now you created invalid JSON again, because "tickFormatter" : function(val, axis){return val.toExponential(2)}, misses the quotes around the function string.
Before you insert the string with str_replace(), you need to take care of escaping and quoting.
You may need a little helper function, which properly escapes a string - to be valid JSON.
you need to use str_replace() correctly: not replacing the outer quotes, just the inner $tickFormatter$.
Wait.. i will provide an example:
// we already have an array, which is JSON encoded
// now you want to insert additional JSON content.
// therefore we use a token replace approach.
// valid JSON - with $token$
$json = '[{"data":[["1","2"],["3","4"]],"tickFormatter":"$tickFormatter$"}]';
// the (future) javascript function is a string.
// it's not properly escaped or quoted to be JSON
// this allows for copy and pasting JS into PHP
$unescaped_functionString = 'function(){return "foo bar";}';
// in order escapre properly, we need a json escaping helper
/**
* #param $value
* #return mixed
*/
function escapeJsonString($value) { # list from www.json.org: (\b backspace, \f formfeed)
$escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
$replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
$result = str_replace($escapers, $replacements, $value);
return $result;
}
// then we escape the function string
$functionString = escapeJsonString($unescaped_functionString);
// now its ready to be inserted into the existing JSON,
// where token $tickFormatter$ is defined
// the token must be in single quotes. you replace just the $token$ and not "$token$".
$json = str_replace('$tickFormatter$', $functionString, $json);
echo $json;
// The result is valid JSON again:
// [{"data":[["1","2"],["3","4"]],"tickFormatter":"function(){return \"foo bar\";}"}]
Next step:
The ajax request is made, the json data is transferred to the client and you want to execute the function you passed in.
So the new question is "How to call/exec a JavaScript function from a string - without using eval?"
In general tunneling is a bad practice, see: Is it valid to define functions in JSON results?
Anyway, there a different ways to do this:
Referencing: http://everythingfrontend.com/posts/studying-javascript-eval.html
eval() - evil, but works.
setTimeout()
setTimeout(" function ", 0);
new Function()
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
document.write
document.write('<script> JS </script>')
data URI
var s = document.createElement('script');
s.src = 'data:text/javascript,' + encodeURIComponent('alert("lorem ipsum")')
document.body.appendChild(s);
JSON cannot contain functions like this.
You can however use Javascript to inject the function into the DOM, so what you want to do is skip the str_replace part and simply create a <script type="text/javascript"></script> element in the DOM and insert the data.function property into there.

Categories

Resources