I have written a C++ module for my Node/Typescript/Javascript frontend and use JSON to pass data back and forth, e.g.
let response = myModule.addCommand("{\"cmd\":\"LoadFile\", \"path\":\"D:\\\\folder\\\\file.abc\"}");
However, I have trouble passing variables, as they are loosing the backslashes each time and so I am currently storing the path variable and use regex to add back the "lost" backslashes each time.
On the C++ side:
std::filysystem::path cppPath = doc["path"].GetString(); // using rapidjson::Document doc
// do stuff
std::string response ="{\"path\":\"" +
std::regex_replace(cppPath.string(), std::regex(R"(\\)"), R"(\\\\)") +
"\"}";
And on the JS/TS side:
// from cpp:
let response = myModule.addCommand(`{\"cmd\":\"LoadFile\", \"path\":\"D:\\\\folder\\\\file.abc\"}`);
let regex = /\\/g;
let usedPath = response.path.replace(regex, "\\\\");
let response = myModule.addCommand(`{\"cmd\":\"SaveFile\", \"path\":\"${usedPath}\"}`);
Is there a more elegant way to do this to pass the variable directly so that it can be used on the other "side"?
Thank you in advance.
Related
I'm trying to interpret an array url param in PHP, but it's interpreted as string instead of an array.
On client side, the url is generated with js:
URL:
let url = window.location.href.split('?')[0] //example https://www.test.com
The get parameters are added with:
const params = encodeURIComponent(JSON.stringify(array));
url += "?array="+params;
for an example array of [1010,1020,1030], the final url looks like:
https://www.test.com?array=%5B%221010%22%2C%221020%22%2C%221030%22%5D
On server side (PHP), I'm using $_GET['array'] to get those data, the output looks like:
string(22) "["1010","1020","1030"]"
It is a syntactically correct array, but interpreted as string.
I know, I could use some string manipulations to get the array I want, but is there a way, that I can get an array right from scratch?
Either decode the current parameters as JSON...
$array = json_decode($_GET['array']);
or encode the array in a way PHP understands natively...
const params = new URLSearchParams();
array.forEach((val) => {
params.append("array[]", val); // note the "[]" suffix
});
url += `?${params}`;
$array = $_GET['array'] ?? [];
In my play framework project I have a confirmed functional Java map of the form Java that is passed to a html page home.scala.html
The map variable is passed in as other (working) variables are, at the top of the page:
#(workingVar1: String, workingVar2: Int, mapVar: Map[Long, Integer])
But developer tools in google chrome highlights this part of the javascript (embedded in home.scala.html's head):
var myMap = #mapVar;
With the error Uncaught SyntaxError: Unexpected token =
So none of the javascript works. What is the correct way to pass this map in?
You can use Java/Scala variables in Twirl Scala templates and both are executed on the server side.
Now on server side Twirl engine translates Java object to something (which probably isn't what you want) and in this form is passed to client, and then this JavaScript is executed.
You want to make sure that client will receive valid JavaScript code.
To assign proper value, you will have to mix some JSON libraries, which will help you assign value in a proper way.
Eg. on the controller side:
...
Map<Long, Integer> map = new HashMap<>();
map.put(1L, 2);
map.put(3L, 3);
String yourMap = Json.stringify(Json.toJson(map));
Now you want to pass yourMap to view, and then you will assign to myMap
using #Html as we want it as raw content fragment:
#(workingVar1: String, workingVar2: Int, mapVar: String)
var myMap = #Html(mapVar);
Try and let me know if it helped.
An inelegant but functional solution is as follows:
Bring in the Java Map as a string:
var stringMap = "#mapVar";
Removes the braces and spaces inserted into the string unnecessarily
stringMap = stringMap.replace(/{/g,'');
stringMap = stringMap.replace(/}/g,'');
stringMap = stringMap.replace(/ /g,'');
Split the mapString by , and for every pair split again by =, extracting keys and values as you go. These will need to be parsed to their correct data-types before adding to a javascript array jsArr:
var pairArray = mapString.split(",");
pairArray.forEach(function(pair) {
var values = pair.split("=");
var longString = values[0];
var intString = values[1];
var myLong = parseFloat(longString);
var myInt = parseInt(intString);
jsArr.myLong = myInt;
}
Where jsArr has been defined previously.
Rendering Data into template res.render('account/pets/allPets', { petMap, title: 'All Pets' })
I have tried two thing to make this work
A)
var neighborhoods = [];
for (var i = 0; i < petMap.length; i++) {
neighborhoods.push(new google.maps.LatLng(petMap[i].location.loc[0],pet.location.loc[1]))
}
B)
var neighborhoods = [
each pet in petMap
new google.maps.LatLng(petMap[i].location.loc[0],pet.location.loc[1])
]
Assuming patMap is a javascript object, you are required to do a few hacky things to make this work. Pug renders serverside, while javascript on the client, so you cannot directly access a pug variable in JS. What you CAN do is convert your js object into a string when the pug compiles, then parse it to JSON when the client executes.
var petMap = JSON.parse(("#{JSON.stringify(petMap)}").replace(/"/g, '"'));
/*
Let me break this down in terms of execution
"#{JSON.stringify(petMap)}" -> executes server side, converts #{} accesses pug variable petMap, which has been converted to an object
.replace(/"/g, '"') -> replaces quote escape sequences (something html does for security) back to quotes so JSON can be parsed
JSON.parse -> parses json from stringified json the server sent to the client
*/
I have this code:
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
localStorage.setItem('added-items', JSON.stringify(string));
This code will use localStorage.
Here is now the code to get the stored data:
var retrievedObject = localStorage.getItem('added-items');
My problem now is, how can i get the size of the data items? answer must be 2.
How can i get the "Item1" and "Item2"?
I tried retrievedObject[0][0] but it is not working.
And how to add data on it?
so it will be
{"items":[{"Desc":"Item1"},{"Desc":"Item2"},{"Desc":"Item3"}]}
Can I use JSON.stringify?
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
localStorage.setItem('added-items', JSON.stringify(string));
stringify means, take an object and return its presentation as a string.
What you have, is already a string and not a JSON object.
The opposite is JSON.parse which takes a string and turns it into an object.
Neither of them have anything to do with getting the size of an array. When properly coding JavaScript you almost never use JSON.parse or JSON.stringify. Only if serialization is explicitly wanted.
Use length for the size of the array:
var obj = {"items":[{"Desc":"Item1"},{"Desc":"Item2"},{"Desc":"Item3"}]}
console.debug(obj.items.length);
// THIS IS ALREADY STRINGIFIED
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
// DO NOT STRINGIFY AGAIN WHEN WRITING TO LOCAL STORAGE
localStorage.setItem('added-items', string);
// READ STRING FROM LOCAL STORAGE
var retrievedObject = localStorage.getItem('added-items');
// CONVERT STRING TO REGULAR JS OBJECT
var parsedObject = JSON.parse(retrievedObject);
// ACCESS DATA
console.log(parsedObject.items[0].Desc);
To bring clarity to future people that may stumble across this question and found the accepted answer to not be everything you hoped and dreamed for:
I've extended the question so that the user may either want to input a string or JSON into localStorage.
Included are two functions, AddToLocalStorage(data) and GetFromLocalStorage(key).
With AddToLocalStorage(data), if your input is not a string (such as JSON), then it will be converted into one.
GetFromLocalStorage(key) retrieves the data from localStorage of said key
The end of the script shows an example of how to examine and alter the data within JSON. Because it is a combination of objects and array, one must use a combination of . and [] where they are applicable.
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
var json = {"items":[{"Desc":"Item1"},{"Desc":"Item2"},{"firstName":"John"},{"lastName":"Smith"}]};
localStorage.setItem('added-items', AddToLocalStorage(string));
localStorage.setItem('added-items', AddToLocalStorage(json));
// this function converts JSON into string to be entered into localStorage
function AddToLocalStorage(data) {
if (typeof data != "string") {data = JSON.stringify(data);}
return data;
}
// this function gets string from localStorage and converts it into JSON
function GetFromLocalStorage(key) {
return JSON.parse(localStorage.getItem(key));
}
var myData = GetFromLocalStorage("added-items");
console.log(myData.items[2].firstName) // "John"
myData.items[2].firstName = ["John","Elizabeth"];
myData.items[2].lastName = ["Smith","Howard"];
console.log(myData.items[2]) // {"firstName":["John","Elizabeth"],"lastName":["Smith","Howard"]}
console.log(myData.items.length) // 4
JSON.parse is definitely the best way to create an object but I just want to add if that doesn't work (because of lack of support), obj = eval('(' + str + ')'); should work. I've had a problem with a HTML to PDF converter in the past that didn't include JSON.parse and eval did the trick. Try JSON.parse first.
Access your object: obj.items[0].Desc;
var object = Json.parse(retrievedObject);
Now you can access it just like an array
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
If you need more help i have some previous code where i am reading Json from local storage and making a form from that json. This code will help in understanding how to traverse that array
Json stored in localstorage
{"form":[{"element":"input", "type":"text","name":"name","value":"value","min":"2","max":"10"}]}
JavaScript to read that json
function readJson(){
if(!form_created){
add_form();
}
var fetched_json = localStorage.getItem("json");
var obj=JSON.parse(fetched_json);
for(var i=0; i<obj.form.length;i++){
var input = document.createElement(obj.form[i].element);
input.name = obj.form[i].name;
input.value = obj.form[i].value;
input.type = obj.form[i].type;
input.dataset.min = obj.form[i].min;
input.dataset.max = obj.form[i].max;
input.dataset.optional = obj.form[i].optional;
form.insertBefore (input,form.lastChild);
}
alert(obj.form[0].name);
}
Basically, I want to make a game in JavaScript and allow a user to get a copy paste-able code which stores their data. In reality, this "code" is actually obfuscated JSON that can be decoded by the application later.
I don't need much security, as I am aware that if people put some effort in they can view/modify the save, and I have no interest in stopping them. I just want the average user to not be tempted and/or see unnecessary information.
Thanks in advance.
you can use base64 encoding to encode your json String. it would be faster approach.
If you with pure javascript :
var encodedData = btoa("stringToEncode");
If you are using nodejs:
base-64 encoding:
var encodedStr = new Buffer("Hello World").toString('base64')
decode to original value:
var originalString = new Buffer("SGVsbG8gV29ybGQ=", 'base64').toString('utf-8')
Well... given that there is no security concern and you only want users to see what appears to be garbled data you can "encode" all the json data
var jsonData = {"key":"value"};
// turn it into a string
var jsonString = JSON.stringify(jsonData);
// replace some letters
var awkardString = jsonString.replace(/a/g, '!Ax6'); // be carefull, you should replace a letter with a pattern that does not already exist on the string.
// encode it with some type of reversible encoding
var garbledData = encodeURI(jsonString);
// output is: %7B%22key%22:%22v!Ax6lue%22%7D
// to "decode" it do the same steps in reverse
awkardString = decodeURI(garbledData);
jsonString = awkardString.replace(/!Ax6/g, 'a'); // now you see, if '!Ax6' existed on the source string, you would loose it and get an 'a' in return. That is why the replacement should be as unique as possible
jsonData = JSON.parse(jsonString);