So basically I have this code:
var string = '{name: "bob", height: 4, weight: 145}';
I would like to know if it is possible to convert that string into an object.
so that I can use
string.name, string.height, and string.weight
(I am retrieving the string variable from a database so I cannot just remove the quotes and make it an object in the first place)
eval, as suggested by Igor, will certainly work but is vulnerable to attack.
Instead you could use a library to parse it for you. There are options in the following link:
Eval is evil... So what should I use instead?
It seems that your string is malformed. In order to work with JSON.parse or even jQuery.parseJSON methods, your keys must have speech marks (" ) around them, like so:
var str = '{"name": "bob", "height": 4, "weight": 145}';
var obj = JSON.parse(str);
You can test this by adding console.log(obj); as the final line. Here is my jsFiddle example.
So try to see if you can pull down the data from the server in the format I have suggested and it can then easily be parsed into a JavaScript object.
I would not use string for a variable name, but:
var obj = eval(string);
alert(obj.name);
or you can use jQuery.parseJSON: api.jquery.com/jQuery.parseJSON.
Related
I have this javascript file which looks like below:
var abc= {
"a" : {
"label": "Monthly",
"URL": "xyz.com",
"ArchTag": "M",
"archData": {
"Feb 2016":"20160229",
"Jan 2016":"20160129",
"Dec 2015":"20151231"
}}};
so I want a way to edit this and say add a new month detail. I guess its a json inside javascript. So how can one edit it in a standard way.
If you can rely on the data looking exactly like this every time then you can just hack off the bit that stops it being JSON:
json_data = json.loads('{' + json_file.read().partition('{')[2])
(or use a regex, or whatever you prefer for string manipulation)
You should still beware that JavaScript is not the same as JSON, so you need some confidence that what you're given will always be an assignment of a valid JSON associative array to a variable.
If, on the other hand, you're being passed arbitrary JavaScript and you're expected to evaluate it, then you have a much bigger problem to solve. What if someone gives you var xyz = "Monthly"; var abc = {"label" : xyz, "URL" : "xyz" + "." + "com"}?
You need a JavaScript engine to solve that more general problem, not just a JSON parser. For example, js2py claims to be a complete JavaScript engine written in Python, but I've never used it so I can't recommend or dis-recommend it.
There are also security issues to consider in executing code from untrusted sources, beyond those you consider if all you're doing is parsing JSON from an untrusted source. So if you need to use a JavaScript engine, make sure you properly understand how it is sandboxed.
Your code is Javascript, not JSON...
With this code in JS you just create a new Object.
But JSON IS NOT A LANGUAGE!!.!
Json is a solution to efficiency store/transmit datas (as assiocative arrays).
Just try to do not define abc:
Your JSON file:
{
"a" :
{
"label": "Monthly",
"URL": "xyz.com",
"ArchTag": "M",
"archData":
{
"Feb 2016":"20160229",
"Jan 2016":"20160129",
"Dec 2015":"20151231"
}
}
}
If you can not remove var abc of your file, read the file in a string, remove the first characters of the string and load the new string.
try:
with open(file) as json_file:
data = file.read()
json_data = json.loads(data[9:])
pprint(json_data)
except Exception as e:
print(e)
if it is not always written var abc then start your string at the first { index.
Actually the file content is not json because of the var you mentioned. you should remove that part dynamically:
json_text = json_file.read().replace('var abc=','')
json_data = json.dumps(json_text)
pprint(json_data)
You can use regex to replace the var assignment piece:
with open('file.txt') as json_file:
data = json_file.read()
data = re.sub(r'^var\s*\S*\s*=\s*', '', data)
json_data = json.loads(data)
I have some data in the form
[
{
"name": "alex",
"fullname": "Alessandro Magno"
},
{
"name": "alex",
"fullname": "Alessandro Magno"
}
]
but (name and fullname) are not fixed, they may be "key"/"value", or whatever.
I'm also given a template to follow, e.g.:
var template = "<span>data.fullname (data.name)</span>".
My problem is the following:
I have to look for all the "data." in the string,
obtain the value following it (in this case, fullname and name),
and replace data. with my external source. E.g.
str.replace("data.<value>", source[value]);
In Javascript.
Thanks!
EDIT: I probably explained it wrongly. My source is defined (in this case, a name/fullname list in JSON format). I also have a template to follow. I have to replace the syntax used in the template (which is "data." ['data.' is fixed]) with the correspondent value of the source. Hope this is clearer now!
Re-thanks!
A simple replace call using a string will only replace a single instance of a substring. You'll have to use a regular expression.
Looking at what you're trying to do, I'd say you're probably looking for something like:
var s = "<span>data.fullname (data.name)</span>";
var replacements = {name: 'alex', fullname: 'alessandro'};//example
s.replace(/(data\.)([a-z]+)/g, function(a,b,c)
{
return b + (repl[c] || 'none');
});
This results in "data.alessandro (data.alex)"
How it works? Central to this approach is the regular expression:
/(data\.)([a-z]+)/g, which is quite basic:
(data\.): match and capture the literal string "data."
([a-z]+): again: match & capture 1 or more chars fater data. -> "data."
g: is the global flag, apply this patter to the entire string.
Now, for each match for this pattern that is found, instead of providing a replacement string, I provide a function, that is passed the matched substring (and the captured groups as separate arguments), and use the function construct a replacement string:
function(a, b, c)
{//a -> entire substring, b-> data., c-> string after data.
return b + (replacements[c] || 'none');// logical || to provide default string replacement
}
It's as simple as that, really. Given that your values are contained by objects, that are in an array, you could opt to code the following:
var vals = [{name: 'alex', fullname: 'alessandro'},{name: 'alex2', fullname: 'alessandro2'}],
results =[],
template = "<span>data.fullname (data.name)</span>";
for (var i=0;i<vals.length;++i)
results[i] = template.replace(/(data\.)([a-z]+)/g, function(a,b,c)
{
return b + (vals[i][c] || 'default');
});
Edit:
To remove data. substring, too, change the callback function (and pattern) to:
s.replace(/data\.([a-z]+)/function(a,c)
{
return replacements[c] || 'none';
});
In case of the code above:
for (var i=0;i<vals.length;++i)
results[i] = template.replace(/data\.([a-z]+)/g, function(a,c)
{
return vals[i][c] || 'default';
});
Is what you're after
If you need to use a template you could use template engine. Basically it will allow you to bind an object to a template. Behind the scene the template is parsed using regex. Pseudo-code:
var template = "<span>{fullname} ({name})</span>";
var html = template({ fullname: data.fullname, name: data.name });
To name a few:
http://handlebarsjs.com/
http://mustache.github.io/
http://underscorejs.org/
Underscore is more a library tool belt, but it provides a simple templating engine that works well for common use.
It is not clear what the transformation you are trying to achieve is, but I can tell you that you should not be using regex to achieve it! Transform your JSON into JavaScript objects using JSON.parse, transform the objects directly, then convert back to JSON via JSON.stringify.
How can a javascript Array be stored in an HTML5 data attribute?
I've tried every variation of JSON.stringifycation and escaping characters.
What is the precise method to store the array and retrieve it again?
note
I build the array with [ $("#firstSelectedElement").val(), $("#secondSelectedElement").val() ]. I retrieve id="storageElement" data-storeIt="stuff" with $("#storageElement").data('storeit').
I can never seem to retrieve the data as a true Array, only an Array of characters.
It turned out that you could use the html escaped characters in the element data attribute to have json-like array (encoded are quotes):
<div id="demo" data-stuff='["some", "string", "here"]'></div>
And then in javascript get it without any additional magic:
var ar = $('#demo').data('stuff');
Check this fiddle out.
Edited (2017)
You don't need to use html escaped characters in the data attribute.
<div id="demo" data-stuff='["some", "string", "here"]'></div>
Check this new fiddle out.
It depends on what type of data you're storing in the array. If it's just strings (as it appears to be) and you have a character that you know will never be a part of your data (like the comma in my example below) then I would forget about JSON serialization and just use string.split:
<div id="storageElement" data-storeIt="stuff,more stuff"></div>
Then when retrieving:
var storedArray = $("#storageElement").data("storeIt").split(",");
It will handle a bit better than using JSON. It uses less characters and is less "expensive" than JSON.parse.
But, if you must, your JSON implementation would look something like this:
<div id="storageElement" data-storeIt='["hello","world"]'></div>
And to retrieve:
var storedArray = JSON.parse($("#storageElement").data("storeIt"));
Notice that in this example we had to use semi-quotes (') around the data-storeIt property. This is because the JSON syntax requires us to use quotes around the strings in its data.
The HTML5 data attribute can store only strings, so if you want to store an array you will need to serialize it. JSON will work and it looks like you're on the right path. You just need to use JSON.parse() once you retrieve the serialized data:
var retrieved_string = $("#storageElement").data('storeit');
var retrieved_array = JSON.parse(retrieved_string);
Reviewing the api documentation, jQuery should try to automatically convert a JSON encoded string provided it is properly encoded. Can you give an example of the value you are storing?
Also note that HTML5 data attribute and jQuery .data() methods are two distinct things. They interact, but jQuery is more powerful and can store any data type. You could just store a javascript array directly using jQuery without serializing it. But if you need to have it in the markup itself as an HTML5 data attribute, then you are limited only to strings.
For the record, it didn't work with encoded entities for me, but seems that in order to be parsed as an object, the data attribute must be a well formed JSON object.
So I was able to use an object with:
data-myarray="{"key": "value"}"
or maybe just use single quotes:
data-myobject='{"key1": "value1", "key2": value2}'
Time to have fun! :D
You can store any object into node like that:
$('#storageElement').data('my-array', ['a', 'b', 'c']);
var myArray = $('#storageElement').data('my-array');
If you need nested arrays or just another way to do it. This works:
$('[data-example]').each(function (i, e) {
var json = $(e).data('example');
for(var index in json){
console.log(json[index]["name"] + "=" + json[index]["value"]);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-example='[{"name": "A", "value": 1}, {"name": "B", "value": 2}]' />
<div data-example='[{"name": "C", "value": 3}, {"name": "D", "value": 4}]' />
as suggested by Ulysse BN
Or with eval() that is a dangerous solution as pointed by Bonifacius Sarumpaet but works
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-example="[['A', 1], ['B', 2]]" />
<div data-example="[['C', 3], ['D', 4]]" />
<script>
$('[data-example]').each(function (i, e) {
var arrayFromText = eval($(e).data('example'));
console.log(arrayFromText[0][0] + "=" + arrayFromText[0][1]);
console.log(arrayFromText[1][0] + "=" + arrayFromText[1][1]);
});
</script>
If using PHP do in PHP:
$arr_test = ['A','C','E'];
$coded = json_encode($arr_test);
// paste coded in data-atribute
print '<div class="funPlus" data-arr_diensten="'. $coded . '"></div>';
The HTML on inspect looks like:
<div class="funPlus" data-arr_diensten="["A","C","E"]"></div>
Now in javascript retrieve the array, but if it has only one value it returns as a string. So you have to test and fix this. If it is a string we have to remove the extra quotes. $(this) has to point to the object.
var arr_diensten = $(this).data("arr_diensten");
if (typeof arr_diensten == "string") arr_diensten = [arr_diensten.slice(1, -1)];
console.log(arr_diensten);
I'm trying to parse a JSON string and I can't get it to work because of illegal chracters - which I cannot find...
Here is what I have:
make = function (el) {
var config = el.getAttribute("data-config");
console.log(config);
var dyn = $.parseJSON(config)
console.log(dyn);
}
var a= document.createElement("Star Icon");
console.log(a);
make(a);
I'm not really sure how to correctly unescape the JSON in my original string "a", so that it works.
Question_:
Which quotation marks do I need to escape to get this to work?
Thanks!
EDIT:
Ok. I figured it out using Jquery (I'd prefer Javascript-only though). This works:
make = function (el) {
var config = el.attr("data-config");
console.log(config);
var dyn = $.parseJSON(config)
console.log(dyn);
}
var c = $('<a href="#" class="template" data-config=\'{"role":"button","iconpos":"left","icon":"star","corners":"false","shadow":"false", "iconshadow":"false", "theme":"a","class":"test", "href":"index.html","text":"Star Icon", "mini":"true", "inline":"true"}\'>Star Icon</a>')
console.log(c);
make(c);
So escaping the start/end quotations of the JSON string seems to do the trick. The actual problem was that I can not use document.createElement with a full string. I can only create the element document.createElement(a) and then set innerHTML. Need to look into this some more.
If someone can tell me a Javascript-only way how to do this, please let me know.
Thanks!
Strings and object keys in JSON must be double quoted. Double quotes in attributes are not valid, so you'll need to escape them with ".
Also, you probably want to use booleans true/false instead of strings "true"/"false".
var a = document.createElement('Star Icon');
Notice this is completely unreadable and #millimoose's suggestion about just setting the attribute afterwards will make this much easier to deal with in the long run.
This code works:
$(this).load($('.pageloadlabel', this).attr('href'), {category: 1});
This code doesn't work:
var data = '{category: 1}';
$(this).load($('.pageloadlabel', this).attr('href'), data);
The question is, how can I make it work?
Your data is not a Javascript object but a string, you can convert it to object by eval e.g.
data = eval('(' + data + ')');
but eval is considered dangerous, so better to parse string as JSON e.g.
data = JSON.parse(data)
For JSON lib you can use json2
It's not JSON, it's a javascript object.
var data = { category: 1 };
If you have a string, you would have to convert it to a object.
And notice that your string is not a valid JSON, see the link for more details.
Take out the quotes, the load function is expecting an object, not a string.
Have you tried to use eval() on data?
var data = '{category: 1}';
$(this).load($('.pageloadlabel', this).attr('href'), eval(data));