Read value from string which looks like jSon format - javascript

I have cookie value stored in following format
{stamp:'HMzWoJn8V4ZkdRN1DduMHLhS3dKiDDr6VoXCjjeuDMO2w6V+n2CcOg==',necessary:true,preferences:true,statistics:true,marketing:false,ver:1}
and i need to read following values of
necessary
preferences
statistics
marketing
Not sure how to to read values correctly, i tried following code assuming it is jSON format
Cookies.get('CookieConsent')
//Parse the cookie to Object
cookieval = Cookies.get('CookieConsent');
console.log(cookieval);
console.log("Necessary: " + Boolean(cookieval.necessary));
console.log("Prefrences: " + Boolean(cookieval.preferences));
console.log("Statistics: " + Boolean(cookieval.statistics));
console.log("Marketing: " + Boolean(cookieval.marketing));
But this code always returns false.
I use following Jquery to read Cookie values https://cdn.jsdelivr.net/npm/js-cookie#2/src/js.cookie.min.js

You do not have JSON format - you have something closer to JS object literal notation, except that it's a string rather than JS code, so can't use JSON.parse unfortunately.
If the values don't have commas or colons, you can split the string by commas and reduce into an object:
const input = `{stamp:'HMzWoJn8V4ZkdRN1DduMHLhS3dKiDDr6VoXCjjeuDMO2w6V+n2CcOg==',necessary:true,preferences:true,statistics:true,marketing:false,ver:1}`;
const obj = input
.slice(1, input.length - 1)
.split(',')
.reduce((obj, str) => {
const [key, val] = str.split(':');
obj[key] = val;
return obj;
}, {});
console.log(obj);
eval is another option, but that's unsafe.

Wrap this string by ( and ). Then parse like as display follow
Attention! But you need be ensure input string (which received from cookie) not contains bad code. Such as unknown injected function. In this case, the function will be executed on client browser, with access to private data (cookie, localStorage, data from html-forms).
const input = "{stamp:'HMzWoJn8V4ZkdRN1DduMHLhS3dKiDDr6VoXCjjeuDMO2w6V+n2CcOg==',necessary:true,preferences:true,statistics:true,marketing:false,ver:1}"
const object = eval("(" + input + ")");
alert(object.necessary);

What about massaging the string into proper JSON, parsing it into a JSON Object, and using the fields from there?
It's less stable in that changes to the input string may break the function, but it is secure in that it's calling JSON.parse() rather than eval().
function reformatCookieInput(inputString) {
inputString = inputString.replace(/'/g, ""); //global strip out single quotes currently wrapping stamp
inputString = inputString.replace(/,/g, `", "`); //global replace commas with wrapped commas
inputString = inputString.replace(/:/g, `":"`); //same idea with colons
inputString = inputString.replace("{", `{"`); //rewrap start of JSON string
inputString = inputString.replace("}", `"}`); //rewrap end of JSON string
return inputString;
}
const input = `{stamp:'HMzWoJn8V4ZkdRN1DduMHLhS3dKiDDr6VoXCjjeuDMO2w6V+n2CcOg==',necessary:true,preferences:true,statistics:true,marketing:false,ver:1}`;
const properJSONObject = JSON.parse(reformatCookieInput(input));
console.log(properJSONObject);

Related

Needing an alternative to eval() and better way for replacing string values

The API i'm working with responds back with a base64 encoded ruby hash (similar to a json object, but specifically for ruby) that has been converted to a string before base64 encoding
From javascript upon retrieving the encoded string, when decoded I get a string in the same shape as the ruby string it originated as on the server
// Decoded example String
"{:example=>'string',:another_example=>'string'}"
I am able to parse out the ruby string to a JSON object using string replace and eval() but I know eval() is evil. Also, there is no way to handle any other key value pairs that may pop up in the future.
How should this be re written with no eval and no direct string replacements?
var storedToken = base64url.decode(window.localStorage.authtoken).replace(':example=>', 'example:').replace(':another_example=>', 'another_example:')
var parsedTokenString = JSON.stringify(eval('(' + storedToken + ')'))
var newJsonObject = JSON.parse(parsedTokenString)
Replace and then JSON.parse:
const storedToken = "{:example=>'string',:another_example=>'string'}";
const json = storedToken
.replace(/:(\w+)/g, '"$1"')
.replace(/=>/g, ':')
.replace(/'/g, '"');
const obj = JSON.parse(json)
console.log(obj);
You will probably want to tighten this up to avoid things breaking when the string values contain things like :foo or escaped single quotes.
However, as mentioned in other answers and comments, you should really change the server to return JSON, which is easy enough with Ruby's to_json.
So you have a string like:
"{:example=>'string',:another_example=>'string'}"
that you'd like to convert to an object like (using JSON):
'{":example":"string", ":another_example":"string"}'
It's unclear to me if the colon before :example is part of the property name or a token indicating a property name, I've assumed it's part of the name (but that's easy to modify).
A regular expression might be used, however if the tokens are:
{ start of notation
=> property name, value separator
, property/value pair separator
} end of notation
Then a simple parser/formatter might be something like:
function stringToJSON(s) {
var resultText = '';
var tokens = {
'{' : '{', // token: replacement
'=>': ':',
',' : ',',
'}' : '}'
};
var multiTokens = {
'=': '=>' // token start: full token
};
var buff = '';
// Process each character
for (var i = 0, iLen = s.length; i < iLen; i++) {
// Collect characters and see if they match a token
buff = s[i];
// Deal with possible multi-character tokens
if (buff in multiTokens) {
// Check with next character and add to buff if creates a token
// Also increment i as using next character
if ((buff + s[i + 1]) in tokens) {
buff += s[++i];
}
}
// Now check in tokens
if (buff in tokens) {
// Tokens are always surrounded by ", except for first { and last }
// but deal with those at the end
resultText += '"' + tokens[buff] + '"';
// Otherwise, deal with single characters
} else {
// Single quotes not allowed
if (buff == "'") buff = '';
// Add buff to result
resultText += buff;
}
}
// Remove leading and trailing "
return resultText.replace(/^\"|\"$/g, '');
}
var s = "{:example=>'string',:another_example=>'string'}";
console.log(stringToJSON(s));
// Convert to object
console.log(JSON.parse(stringToJSON(s)));
Your string notation might be more complex, but I think you get the gist of it. You may need to trim whitespace around tokens, but since the property names aren't surrounded by quotes it's hard to know what to keep and what to throw away. You could include tokens in the data by quoting, then throwing away the quote character, e.g.:
\=>
could be treated as the literal "=>", not a token.
More tokens and processing steps can be added fairly easily. The multi-character tokens can get interesting, especially if you go to 3 or for characters.
Array methods and regular expressions can be used for token matching and processing, however I think loops are a good place to start to get the logic sorted, sugar can be added later.

Convert a string of array into array javascript

In my code i am reading a hidden input value which is actually a javascript array object
<input type="hidden" id="id_num" value="{{array_values}}">
But when i taking it using jquery ($('#id_num").val()) its a string of array,
"['item1','item2','item3']"
so i can not iterate it.How should i convert into javascript array object, so that i can iterate through items in the array?
You can use JSON.parse but first you need to replace all ' with " as ' are invalid delimitters in JSON strings.
var str = "['item1','item2','item3']";
str = str.replace(/'/g, '"');
var arr = JSON.parse(str);
console.log(arr);
Another approach:
Using slice and split like this:
var str = "['item1','item2','item3']";
var arr = str.slice(1, -1) // remove [ and ]
.split(',') // this could cause trouble if the strings contain commas
.map(s => s.slice(1, -1)); // remove ' and '
console.log(arr);
You can use eval command to get values from string;
eval("[0,1,2]")
will return;
[0,1,2]
more details here
Though it should be noted, if this string value comes from users, they might inject code that would cause an issue for your structure, if this string value comes only from your logic, than it is alright to utilize eval
var arr = "['item1','item2','item3']";
var res = arr.replace(/'/g, '"')
console.log(JSON.parse(res));
A possible way of solving this:
First, substr it to remove the [..]s.
Next, remove internal quotes, since we would be getting extra when we string.split
Finally, split with ,.
let mystring = "['item1','item2','item3']";
let arr = mystring.substr(1, mystring.length - 2)
.replace(/'/g, "")
.split(",")
console.log(arr)

From string to an Object with Javascript

How can I convert this string: "{one=1,two=2}" into an object with JavaScript? So I can access the values.
I tried replacing the "=" for ":", but then while accessing the object I receive an "undefined". Here is my code:
var numbers = "{one=1,two=2}"; //This is how I receive the string
numbers = numbers.replace(/=/g, ':'); //I use the '/g' to replace all the ocurrencies
document.write(numbers.one); //prints undefined
So this is the string
var str = '{one=1,two=2}';
replace = character to : and also make this as a valid JSON object (needs keys with double-quotes around)
var str_for_json = str.replace(/(\w+)=/g, '"$1"=').replace(/=/g, ':');
In regex, \w means [a-zA-Z0-9_] and the ( ) capture what's inside, usable later like here with $1
Now parse your string to JSON in order to use like that
var str_json = JSON.parse(str_for_json);
Now enjoy. Cheers!!
document.write(str_json.one);
FINALLY :
var str = '{one=1,two=2}';
var str_for_json = str.replace(/(\w+)=/g, '"$1"=').replace(/=/g, ':');
try {
var str_json = JSON.parse(str_for_json);
document.write(str_json.one);
} catch(e) {
console.log("Not valid JSON:" + e);
};
Instead of trying to use regexp to create JSON, I would simply parse the string directly, as in
const result = {};
numbers.match(/{(.*?)}/)[1] // get what's between curlies
.split(',') // split apart key/value pairs
.map(pair => pair.split('=')) // split pairs into key and value
.forEach(([key, value]) => // for each key and value
result[key] = value); // set it in the object
1 - a valide JSON is :var numbers = "{\"one\"=1,\"two\"=2}"; (you need the \")
2- you need to JSON.parse the strign
So this works:
var numbers = "{\"one\"=1,\"two\"=2}"; //This is how I receive the string
numbers = numbers.replace(/=/g, ':'); //I use the '/g' to replace all the ocurrencies
numbers=JSON.parse(numbers);
document.write(numbers.one); //prints undefined
But, it's bad practice !

How to replace specific parts in string with javascript with values from object

I want to make custom replacer method for my HTML output. But I can't figure it out. I guess it should be done with String.match and replace somehow.
I have some "error codes" in my string that always start with _err_ and I have a JS object with values.
What I want to achieve:
Find all string parts (error codes) that starts with _err_
Get correct key for my object - error code without _err_
Find value from Lang object
Replace error code with correct Lang value.
Some error codes may appear multiple times.
var content = "Looks like you have _err_no_email or _err_no_code provided";
var Lang = {
'no_email' : "No email",
'no_code' : "No code"
};
I can do it other way around. So I cycle the Lang object and replace those in string.
It would be something like this if using underscore:
function replaceMe() {
_.each(Lang, function(value, key) {
content = content.replace(new RegExp('_err_' + key,'g'), value);
});
console.log(content);
};
But if it can be done faster with my first idea then I want to know how.
A simple regex should do the trick:
var content = content.replace(/\b_err_(.+?)\b/g, function(match, errorName) {
return Lang[errorName] || match;
});
This assumes that you do not want strings like "blah_err_blah" to be replaced, and defaults to not replacing the text if the error cannot be found in your Lang object.
var replace = function(str, object, regexp) { //if property not found string is not replaced
return String(str).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name) {
return (object[name] != null) ? object[name] : match;
});
}
This is a format function I've used in several projects thats quite efficient. Matches {prop} by default to {prop:'val'} but you can pass a regex for example maybe in your case /_err_+\S/g so it matches other tokens in your string.
So you can do:
var content ="Looks like you have {no_email} or {no_code} provided";
var Lang = {
'no_email' : "No email",
'no_code' : "No code"
}
var formatted = replace(content, lang);
Or for your original string stealing the other answers regex:
var formatted = replace(content, lang, /_err_([^\s]+)/g)
You can use a callback function, that look if a key matching the error code exists in your Lang object, and if so returns the value of that (and otherwise just the key itself, thereby doing no replacement, like so:
content.replace(/_err_([a-z_]+)/gi, function(fullmatch, key) {
return Lang[key] ? Lang[key] : fullmatch;
});
The first parameter passed to the function will be the full match, and the second parameter key will just be that part grouped by the bracktes.
And then, if Lang contains a (non-falsy) value for key, that’ll be returned, otherwise just the fullmatch value, so that that part of the string gets “replaced” with itself.
See it in action here: http://jsfiddle.net/VZVLt/1/
One more variation with split
content = content
.split('_err_')
.map(function(str, index){
if (index === 0)
return str;
var whitespace = str.indexOf(' '),
key = str.substring(0, whitespace)
return Lang[key] + str.substring(whitespace);
})
.join('')
;

Manipulate (str.replace) array data that comes back over autocomplete

$('#groupnamesearch').blur(function () {
str = $('#groupnamesearch').val()
$.get("injectgroup.php", {
name: str
}, function (data) {
//here i guess str.replace data
$('#aspecforgroup').val(data);
});
});
This gives me results like: ["45054","55905","42306"]
I'd like to strip all []" of them, so I have only numbers and the , character.
How can I manipulate the data that came over the ajax request before it's getting populated in an input field?
Thanks :)
If the result that you are getting back in data is an actual string - and I assume it must be if the square brackets are getting displayed in your "aspecforgroup" field - then you can remove those characters as follows:
data = data.replace(/[\[\]"]/g, "");
Or you can tell jQuery (that is jQuery that you're using?) to treat the response as JSON in which case it should be automatically parsed into an array by the time it ends up in the data parameter and then you can use the array .join() method to turn that into a string:
$.get("injectgroup.php", {
name: str
}, function (data) {
$('#aspecforgroup').val(data.join(","));
}, "json");
The parameter to .join() is the string to join the individual elements with. If you leave it out it will be a comma by default, but you might want to use a comma plus a space: .join(", ").
You can do this with array join
if your data is string, you have to first parse the string to convert an array and then do a join like this -
var newData = JSON.parse(data).join();
if data is a string:
data = '["45054","55905","42306"]';
var output​ = JSON.parse(data).join(', ');
​alert(output)​;
if data is already an array:
data = ["45054","55905","42306"];
var output = data.join(', ');
alert(output);
both output this:
45054, 55905, 42306

Categories