I'm having issues with consuming Out Parameters from mySql in node JS when they contain #, I've searched for similar question but can't see any answers to my specific question:
Here's the procedure (not my code)
CREATE PROCEDURE `getuser`(IN `p_googleemail` varchar(64),
out `p_userjson` json)
SET #'p_userJSON' =
(
SELECT json_object('email', USER.email, 'lastName', USER.lastname, 'firstName', USER.firstname )
FROM test.USER
WHERE email = p_googleemail);
select #p_userJSON;
end
Here is a snippet of my Node Code:
/* GET users listing. */
router.get('/', function(req, res, next) {
getConnection(function(err, con) {
googleEmail ='test#gmail.com';
que = 'CALL test.getUser(?, #p_userJSON);';
con.query(que,[googleEmail], function(err, results) {
if (err) throw err;
con.release();
res.send(results);
});
});
});
This is the response:
[
[{
"#p_userJSON": "{\"email\": \"test#gmail.com\", \"lastName\": \"test\", \"firstName\": \"test\"}"
}],
{
"fieldCount": 0,
"affectedRows": 0,
"insertId": 0,
"serverStatus": 34,
"warningCount": 1,
"message": "",
"protocol41": true,
"changedRows": 0
}
]
How do I return the results from #p_userJSON as part of my rest service? I understand I'll have to unescape the json from the out param but I can't even return the #p_userJSON value.
Many thanks!
Edit:
My hack to get around the issue for the minute, this not the full code as got some error handling if there are no results (probably a better way but I've only been using js for a few weeks)
var datapackstr = JSON.stringify(results[0]);
var datapack = JSON.parse(JSON.parse(datapackstr.substring((datapackstr.lastIndexOf('#p_userJSON') + 12) + 1).slice(0, -2)));
Even though this thread is 6 years old I came across basically the same issue with the #. The problem is with the JSON string that's being returned and JSON.parse's ability to deal with the stirngs in #p_userJSON.
The below JSON string works as expected.
var result = '[[{"#p_userJSON": "{\\\"email\\\": \\\"test#gmail.com\\\", \\\"lastName\\\": \\\"test\\\", \\\"firstName\\\": \\\"test\\\"}"}],{"fieldCount": 0,"affectedRows": 0,"insertId": 0,"serverStatus": 34,"warningCount": 1,"message": "","protocol41": true,"changedRows": 0}]';
var res = JSON.parse(result);
console.log(res[0][0]['#p_userJSON']);
You can see a working example in a node fiddle here.
I did need to make some manual changes to the JSON. Remember that JSON.parse won't throw an error when it fails to return an actual JSON object it will simply return an object for each character in the input string.
You can find more info about the JSON.parse function here.
Related
I'm learning Postman. I have a query that returns random values from a key:
GET https://apitest.backendless.com/A1DA5DF0-8D22-BAC4-FF56-9A0074DC9B00/8834B7F8-88BD-4472-9051-71BE31A3EE5B/hive/rootKeys/set/root1/random?count=2
You can use a working request. The key contains the values ["1", "2", "3", "4", "5"]
The question is: how do I write tests for a query that returns random values? Here is a test
let jsonData = JSON.parse(responseBody);
pm.test("Random values", function(){
pm.expect(jsonData).to.eql(["1", "2"])
})
won't do because it might return ["3", "5"]. How then to check the validity of the request?
A very basic check could be something like this:
let response = pm.response.json();
pm.test("Random Number Check", () => {
pm.expect(response, "Response contains a number not in the array").to.contain.oneOf(["1", "2", "3", "4", "5"]);
});
I've created a postman request for you to test directly (https://www.postman.com/southlondon/workspace/playground/request/19391207-0bbb11cb-249c-4fe2-963e-5b73b8cabc9b). It sends a payload with a random array with values from 1 to 5. You can click send several times and see the differences. You can open that link and test it. The test itself tries to validate that only values from 1 to 5 exist in the array:
pm.test("Check that array only contains numbers from 1 to 5 ", function () {
let jsonData = pm.response.json();
let array = jsonData.data
array.every( x => x >= 1 && x <=5 )
});
This covers scenarios where the data would send a value outside the range you described.
I need a better understanding about stringify, escape and storing in mysql database. The task looked easy but with escaping I run into some trouble. So I would be happy for general explanation of the following questions:
What I try is to store a javascript object in a mysql DB. It works fine with stringify prior to send. Getting it back from the DB just parse it and everything is fine.
let myObj = {
name: 'Paul',
age: '24'
}
Now, I have additionally a message in my object, which can have special characters:
let myObj = {
name: 'Paul',
age: '24',
message: 'message with special characters: ',`´"~'
}
Also no problem, I started to escape. The result:
let myObj = {
name: 'Paul',
age: '24',
message: 'message with special characters: \'\,\`´\"\~'
}
If I do stringify the object, I get following result:
{
"name": "Paul",
"age": "24",
"message": "message with special characters: \\'\\,\\`´\\\"\\~"
}
Sending it to mysql DB gives following error:
(node:13077) UnhandledPromiseRejectionWarning: Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\,\`´\"\~"}
Due to the error I manipulated the special characters and removed the additional '\' which gives following result:
obj.message = obj.message(/\\\\/g,'\\');
output:
{
"name": "Paul",
"age": "24",
"message": "message with special characters: \'\,\`´\\"\~"
}
everything is fine and the data is transfered to the DB and my mysql update query has no failure anymore.
Questions:
Is there a better way dealing with escaping inside an object, which will be stringified and send to a mysql DB?
If yes, how is it done? Or is there no other way as to remove the additional backslashes inserted due to the stringify?
One step further. The message has included a new line: \n:
output stringified:
{
"name": "Paul",
"age": "24",
"message": "message with special characters: \'\,\`´\n\\"\~"
}
Sending it to the DB I get following entry (Where \n: I get a new line):
{"name":"Paul","age":"24","message":"message with special characters: ',`´
\"~"}
Which results in an error parsing it back. here is the log (serverside) prior parsing (error makes sense):
{"name":"Paul","age":"24","message":"\',`´\n' +
'\\"~"}
Question:
Regarding the upper part, what do I have to do, to get the \n also escaped? Which means, that the DB entry is correct and the DB doesn't take the \n to start a new line?
Happy for any explaning / help!
I don't know how's the correct way or the easy way, but that's how I did it when I needed to insert a user generated field as a JSON in a MYSQL database
string_cleanJSON_preStringify(str)
{
if(!str.replace) return str;
str=str.replace(/'/g,"\\'"); //escape all at least ' once
str=str.replace(/"/g,'\\"'); //escape all at least " once
str=str.replace(/[\t\r\n\f]/g,''); // remove problematic escape characters
if(str.charAt(str.length-1) == '\\') str+=' '; // add blank space at the end if \ is last character - for example: {"var":"\"} would be problematic
return str;
}
string_cleanJSON_to_query(str)
{
str = str.replace(/(\\)+\\/g,'\\'); // replace all \ more than 1 in a row, to be just 1 ( \\ -> gets escaped again when it's processed to just \)
str = str.replace(/(\\)+"/g,'\\\\\\"'); // replace all \" more than 1 (ex \\\") - i don't know why \\\\\\ - this seem to work in my case, might need to alter based on str manipulations before insert
str = str.replace(/(\\)+'/g,"\\'"); // i don't know why \\ - this seem to work in my case, might need to alter based on str manipulations before insert
str = str.replace(/(\\)+t/g,"t"); // same process as above but with problematic escape characters
str = str.replace(/(\\)+r/g,"r");
str = str.replace(/(\\)+n/g,"n");
str = str.replace(/(\\)+f/g,"f");
return str;
}
How I use this to get a query:
let o = {field_data:string_cleanJSON_preStringify(user_gen_field_data)}
let j = string_cleanJSON_to_query(JSON.stringify(o));
let q = `INSERT INTO blabla (json) VALUES('${j}')`;
Currently my NodeJS code sends JSON back in the following format;
{"data":
[
{"audioname":"mytalk.m4a","name":"Josie ","email":"josie#gmail.com"},
{"audioname":"mytalk40.m4a","name":"Jessie James","email":"jesse#gmail.com"},
{"audioname":"mytalk.m4a","name":"Joan Bologney","email":"joan#gmail.com"}
]
}
But I'd like to get rid of the "data" and send back just;
[
{"audioname":"mytalk.m4a","name":"Josie ","email":"josie#gmail.com"},
{"audioname":"mytalk40.m4a","name":"Jessie James","email":"jesse#gmail.com"},
{"audioname":"mytalk.m4a","name":"Joan Bologney","email":"joan#gmail.com"}
]
Here's the query;
query = mysql.format(query);
connection.query(query,function(err,data){
if(err) {
res.json({"Error" : true, "Message" : "Error executing MySQL query"});
} else {
res.json({data});
}
});
If the object shown above is available though the data variable, we can pass only the data array by using:
res.json(data.data);
Where the second data references to the data array in the data variable.
Small example:
const data = {"data": [{"audioname":"mytalk.m4a","name":"Josie ","email":"josie#gmail.com"}, {"audioname":"mytalk40.m4a","name":"Jessie James","email":"jesse#gmail.com"}, {"audioname":"mytalk.m4a","name":"Joan Bologney","email":"joan#gmail.com"} ] };
console.log(data.data);
Removing the inner brackets seemed to work;
res.json(data);
I have this array in Node.JS as a result of the MySQL query.
let GetTotalMoney = "SELECT sum(total) FROM request WHERE is_completed = 1";
connections.query(GetTotalMoney, function(err, result, fields){
console.log(result) // result is [{ "sum(total)": "1091.75" }]
})
It Gives a weird JSON as cuz I never seen it before the result is [{ "sum(total)": "1091.75" }]
How can i parse it or get the value inside it
I'm trying to get certain data from a json link:
bittrex.com/api/v1.1/public/getticker?market=BTC-DRS
in my node IRC bot using:
https://www.npmjs.org/package/node.bittrex.api
Part of the code:
var url = ('https://bittrex.com/api/v1.1/public/getticker?market=BTC-DRS');
bittrex.options({
'apikey' : settings.ticker.apikey,
'apisecret' : settings.ticker.secretkey,
'stream' : false,
'verbose' : false,
'cleartext' : true,
});
case 'ticker':
var user = from.toLowerCase();
bittrex.sendCustomRequest(url, function(ticker, err) {
if(err) {
winston.error('Error in !ticker command.', err);
client.say(channel, settings.messages.error.expand({name: from}));
return;
}
winston.info('Fetched Price From BitTrex', ticker);
client.say(channel, settings.messages.ticker.expand({name: user, price: ticker}));
});
break;
It works but outputs in IRC
[1:21am] <nrpatten> !ticker
[1:21am] <DRSTipbot> nrpatten The current DRS price at BitTrex {"success":true,"message":"","result":{"Bid":0.00000155,"Ask":0.00000164,"Last":0.00000155}}
I have used a couple of things to get it to show only "Last" from the reply but i keep getting errors.
Or get certain data from https://bittrex.com/api/v1.1/public/getmarketsummaries
Like any info i want from:
{"MarketName":"BTC-DRS","High":0.00000161,"Low":0.00000063,"Volume":280917.11022708,"Last":0.00000155,"BaseVolume":0.33696054,"TimeStamp":"2014-10-04T15:14:19.66","Bid":0.00000155,"Ask":0.00000164,"OpenBuyOrders":33,"OpenSellOrders":138,"PrevDay":0.00000090,"Created":"2014-06-18T04:35:38.437"}
Thanks for any help
Assuming you've parsed the JSON (e.g. via JSON.parse(str);), you just use whatever property name you want to get at. For example:
var info = JSON.parse('{"MarketName":"BTC-DRS","High":0.00000161,"Low":0.00000063,"Volume":280917.11022708,"Last":0.00000155,"BaseVolume":0.33696054,"TimeStamp":"2014-10-04T15:14:19.66","Bid":0.00000155,"Ask":0.00000164,"OpenBuyOrders":33,"OpenSellOrders":138,"PrevDay":0.00000090,"Created":"2014-06-18T04:35:38.437"}');
console.log(info.Bid);
Also, on an unrelated matter, typically callback parameters follow the error-first format (e.g. (err, result) instead of (result, err)) in order to be consistent with node core and most other modules on npm.