Creating a JSON object in JavaScript dynamically - javascript

I need to create a JSON object dynamically in JavaScript using a for loop. I have tried using the array.Push method but it is not working. I am only getting the first value getting stored. The remaining values of the iteration are not getting stored.
This is what I am trying:
var array = [];
for (var i = 0; i < 4; i++) {
var username = drlist.reportees[i].name;
var think40 = getthink40(n,m);
if (think40.isSuccessful){
var result = think40.array;
var length = result.length;
var tes= 0;
for (var j = 0; j < length-1; j++){
tes = tes + parseFloat(result[j].duration);
}
var hours = tes/60;
var think = (hours/40)*100;
if (think > 100)
{
think =100;
}
array.push( {
name: username,
hours: think
});
}
return array;
}

Try this...
var jsonArray = [];
function test (){
for (var i=0; i<3;i++)
{
var jsonObject = {'a':1, 'b':2}; jsonArray.push(jsonObject);
}
return jsonArray;
}
Note : You are returning the jsonObject instead of jsonArray. You should probably return the jsonArray.

Creating and manipulating a JSON object in JavaScript is not very different from any other type of object, but does have a few limitations. These are primarily around the data types JSON supports and the two most notable are a lack of dates and functions.
JavaScript objects can contain almost anything (increasingly so with ES6 and symbols) but JSON is a limited subset of that. The JSON spec is short and easy to read (complete with pictures!), so I would recommend starting there. As you'll see in the spec, the value types include strings, numbers, objects, array, boolean keywords, and null. There is no support for dates -- easily worked around by formatting them as ISO 8601 strings -- or functions.
To turn a valid JavaScript object into the final JSON form involves a limited amount of string formatting and escaping. Most modern browsers have a global JSON API for doing that, providing both parse and render (stringify) methods. This is your codec and the first and final step when manipulating JSON.
In your example, you would build the object as normal, assigning properties (foo.bar = 3) as necessary. At the very end, to return the JSON (which is really just a string in JS), you would take the object you've created and pass it to JSON.stringify. This will produce a valid, safe, escaped JSON string suitable for passing to web services and other scripts.

Related

How can I retrieve value from a string of list of map

I have some requirement like I need to get the values from a map actually where the format is as below:
"{xyz=True, abc=asd-1123, uvw=null}"
to get the values from this map which is in string.
I tried to use JSON.parse("{xyz=True, abc=asd-1123, uvw=null}") and also tried using var map = new Map(JSON.parse("{xyz=True, abc=asd-1123, uvw=null}"))
But neither way it was not working
well to start, json.parse is not going to work as that is not valid json. you are going to need to do the parsing yourself. So assuming everything is consistently in that method, you should start by stripping off the curly braces then breaking down your values and creating your map from those values.
So as an example:
let map = new Map(); // or create an object: {}, because you can get values using Object.values(yourObject)
let mapStr = "{xyz=True, abc=asd-1123, uvw=null}".slice(1, -1);
let kvp = mapStr.split(', ');
for(let i = 0; i < kvp.length; i++) {
let splitVal = kvp[i].split(=);
map.set(splitVal[0], splitVal[1]);
}
Then you can just use the map object you created.
Take into consideration this assumes none of your key-value-pairs have an "=" sign in them. you can also further investigate regexs to generate your maps. either way, it's on you to do the mapping unless there is a library that does this for you already in existence :)

node.js change in concatenation?

I'm trying to debug some code that another programmer has left for me to maintain. I've just attempted to upgrade from node.js 5 to node.js 8 and my database queries are for some requests coming back with key not found errors
We're using couchbase for the database and our document keys are "encrypted" for security. So we may have a key that starts like this "User_myemail#gmail.com" but we encrypt it using the following method:
function _GetScrambledKey(dbKey)
{
//select encryption key based on db key content
var eKeyIndex = CalculateEncryptionKeyIndex(dbKey, eKeys.length);
var sha = CalculateSHA512(dbKey + eKeyIndex);
return sha;
}
function CalculateEncryptionKeyIndex(str, max)
{
var hashBuf = CalculateSHA1(str);
var count = 0;
for (var i = 0; i < hashBuf.length; i++)
{
count += hashBuf[i];
count = count % max;
}
return count;
}
We then query couchbase for the document with
cb.get("ECB_"+encryptedKey, opts, callback);
In node5 this worked but in node8 we're getting some documents return fine and others return as missing. I outputted the "ECB_"+encryptedKey as an int array and the results have only confused me more. They are different on node5 to node8 but only by one character right in the middle of the array.
Outputting the encryptedKey as an int array on both versions shows this
188,106,14,227,211,70,94,97,63,130,78,246,155,65,6,148,62,215,47,230,211,109,35,99,21,60,178,74,195,13,233,253,187,142,213,213,104,58,168,60,225,148,25,101,155,91,122,77,2,99,102,235,26,71,157,99,6,47,162,152,58,181,21,175
Then outputting the concatenated string, in the same way, shows slightly different results
This is the node8 output
Node8 key: 69,67,66,95,65533,106,14,65533,65533,70,94,97,63,65533,78,65533,65533,65,6,65533,62,65533,47,65533,65533,109,35,99,21,60,65533,74,65533,13,65533,65533,65533,65533,65533,65533,104,58,65533,60,65533,25,101,65533,91,122,77,2,99,102,65533,26,71,65533,99,6,47,65533,65533,58,65533,21,65533
And this is the node5 output
Node5 key: 69,67,66,95,65533,106,14,65533,65533,70,94,97,63,65533,78,65533,65533,65,6,65533,62,65533,47,65533,65533,109,35,99,21,60,65533,74,65533,13,65533,65533,65533,65533,65533,65533,104,58,65533,60,65533,65533,25,101,65533,91,122,77,2,99,102,65533,26,71,65533,99,6,47,65533,65533,58,65533,21,65533
I had to run it through a diff tool to see the difference
Comparing that to the original pre-append array it looks like the 225 has just been dropped in node8. Is 225 significant? I can't understand how that would be possible otherwise unless it's a bug. Does anyone have any ideas?
Looks like this was a change in v8 5.5 https://github.com/nodejs/node/issues/21278
A lot of the issues you are facing, including the concatenation can be cleaned up using newer features from ES6 that are available in node 8.
In general, you should avoid doing string concatenations with the + operator and should use string literals instead. In your case, you should replace the "ECB_"+encryptedKey with `ECB_${encryptedKey}`.
Additionally, if you want to output the contents of the integers values from this concatenated string, then you are better off using .join, the spread operator (...) and the Buffer class from Node as follows:
let encKey = `ECB_${encryptedKey}`;
let tmpBuff = Buffer.from(encKey);
let buffArrVals = [...tmpBuff];
console.log(buffArrVals.join(','));
Also, if you can help it, you really should avoid using var inside of function blocks like it exists in your sample code. var performs something called variable hoisting and causes the variable to become available outside the scope it was declared, which is seldom intended. From node 6+ onward the recommendation is to use let or const for variable declarations to ensure they stay scoped to the block they are declared.

How to store and retrieve JSON data into local storage?

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);
}

Matching Array to JavaScript Matrix

I’m wondering how to solve a matching/lookup problem and I “think” a multi-dimensional array is the solution. In short, I want to match a list of comma separated SKUs stored as a cookie value against a finite list of SKUs with matching product names and print out the matched product names onto the page. I’m not sure if this is the best way to do this, but with what I have so far I’m not clear how to properly breakup the comma separated strings from the cookie (right now it’s trying to match the entire cookie value), match them to the matrix (17 total rows) and then print out the Product Name.
<script>
var staticList = [
[“1234”, “Chocolate Ice Cream”],
[“1235”, “Peanut Butter Cookie”],
[“6G2Y”, “Raspberry Jell-O”],
[“YY23”, “Vanilla Wafers”]
];
var cookieSkus = [‘1235,YY23’]; // comma separated value from cookie
jQuery(function () {
for (var i = 0; i < staticList.length; i++) {
if (cookieSkus.indexOf(staticList [i][0]) > -1) {
jQuery('#pdisplay).append(staticList [i] [1] + '<br />');
}
}
});
</script>
<p id=”pdisplay”></p>
In this example, the paragraph "pdisplay" would contain:
Peanut Butter Cookie
Vanilla Wafers
Is there a way to correct what I have above or is there a better method of accomplishing what I’m trying to do?
First, you might want to focus on the Cookie SKUs rather than the staticList. The reason for this is that the cookie may have a variable number, and may be as small as 0 elements. (After all, we don't need to list the items if there are no items).
This may be accomplished simply by converting the string to an array and then checking if the SKU is in the staticList. Unfortunately, since you are using a multidimensional array, this would require going through the staticList for each cookie sku. Using just this suggestion, here is a basic example and fiddle:
Rewrite: Accounting for the fact that staticList is an Array of Arrays
jQuery(function() {
var skus = cookieSkus[0].split(',');
for (var i = 0; i < skus.length; i++) {
for (var j = 0; j < staticList.length; j++) {
if (staticList[j][0] == skus[i]) {
jQuery('#pdisplay').append(staticList[j][2] + '<br/>');
break; // Will end inner if the item is found... Saves a lot of extra time.
}
}
}
});
Edit 2: Using an Object (A possibly better approach)
According to the comments, you must support IE8. In this case, you might consider an Object instead of a multi-dimensional array. The reasons for this are as follows:
An object is actually an associative array (with a few perks).
You can directly check for property existence without having any nested arrays.
Object property access is typically faster than looping through an array
You can access object properties nearly exactly like accessing an array's elements.
When using an Object, the original version of my code may be used without modification. This is because the object's structure is simpler. Here is a fiddle for you: option 2
var staticList = {
"1234": "Chocolate Ice Cream",
"1235": "Peanut Butter Cookie",
"6G2Y": "Raspberry Jell-O",
"YY23": "Vanilla Wafers"
};
jQuery(function() {
var skus = cookieSkus[0].split(',');
for (var i = 0; i < skus.length; i++) {
if (staticList[skus[i]])
jQuery('#pdisplay').append(staticList[skus[i]] + '<br/>');
}
});
Responding to your comment:
The reason that the output matches what is desired is because unlike an array which has numerical indices, the object's indices are the actual skus. So, there is no staticList[0] if staticList is an object. Instead (in the context of the staticList object), 1234 = "Chocolate Ice Cream". So, an object definition basically goes as follows:
var objectName = {
index1: value1,
index2: value2,
...,
...
}
The index may be any primitive value (integer or string). The value may be any valid javascript value including a function or an inner object. Now, to get the value at a specific index, you may do either:
objectName.index1 (no quotes)
OR:
objectName["index1"] (quotes needed if the index is a string)
The result of either of those will be:
value1
It's as simple as that.
I would try something like this:
var cookieSkus = cookieSkus[0].split(',');
staticList.filter(function(cell){
return cookieSkus.some(function(val){return cell[0] === val; });
}).map(function(cell){
jQuery('#pdisplay).append(cell[1] + '<br />');
});
Disclaimer: provided based on the sample code provided above along with recent comments

Saving Javascript object

I have tree of javascript objects. Let's call it "family. It can contain any number of certain objects ("parents") which can each contain any number of "child" objects. The number of levels in this structure is known and each level of the tree only contains objects of one certain type.
All the objects have data and methods.
I want to save the structured data in the databese. JSON.stringify() does it perfect extracting the data and also saving the structure. But how to get back to objects? JSON.parse() fails, because it recreates the object without methods.
What should I do in this case? Should I write my own function for recreating the object from string? Or should I save the data together with methods somehow (seems a waste).
As I know the structure, it would be very handy if there would be a possibility to point to an object and tell "that's a parent object" and it would get the methods. I could easily cycle through it then. But I don't know how to that and I'm also afraid that my constructors could set some values to the default ones.
The objects constructors would look something like this:
function lines()
{
this.lines = [];
this.height = 0.5*theMargin;
this.addLine = addLine;
function addLine(newline)
{
this.lines.push(newline);
this.height += newline.height;
}
}
function aLine()
{
this.dots = [];
this.height = 0;
this.length = indent;
this.insertDot = insertDot;
function insertDot(pos,newDot)
{
this.dots.splice(pos,0,newDot);
this.length += newDot.length;
this.height = Math.max(this.height,newDot.height);
if (this.length > maxLineLength)
{ "I will not go into details here" }
}
}
Then I would do like:
var a = new lines();
var testline = new aLine();
var testdot = new aDot();
testdot.height = 10;
testdot.length = 15;
testline.insertDot(0,testdot);
a.addLine(testline);
a.addLine(testline);
Then I want to save the data about lengths and heights. And the structure, to know which dot belongs in which line.
I send that data to the webserver. I think these are the key lines to understand the used approach:
post = "name=" + name + "&tab=" + JSON.stringify(file);
req.open("POST", "saveFile.php", true);
req.send(post);
The saved file saves exactly what I wanted - the structure and data. But I don't know how to make it become an object again. I am not insisting to use JSON.stringify() method. I would enjoy any approach that would let me save the content without repeatedly saving the methods.
If you are really hooked on the idea of saving the entire object for some reason then I suggest you use the toString() method of which will essentially return the code body of a function in the form of a string when called on a function.
var obj = { func: function() { alert('hello!'); };
for(var key in obj)
if (typeof obj[key] === 'function')
alert(obj[key].toString());
You would just have to add code to serialize and store this information in addition to the json data.
All that said, you really should be simply storing the state of your objects and reloading them into your application.
EDIT: Reconstructing the object client-side
Disclaimer: I am not a PHP guy so you will be left to finding an actually coding example but I'm confident there is one out there with the power of the almighty Google.
You simply need to use your serializing/deserializing class to serialize the data back into your object.
So imagine the section of pseudo code is the php file for the particular page in question:
<?php
<html>
<head>
<script type="text/javascript">
var model = /* Use serializing class on your server-side object */;
//Now you just need to build a function into your objects that is much like a constructor that can receive this model and rebuild the object
function rebuildObject(yourObject, jsonModel) {
//assign first property
//assign second etc...
}
</script>
</head>
<body>
</body>
</html>
?>
You are essentially templating the json data back to the page in a script tag so you can access it client-side. The javascript interpretter will automatically convert the json into an actual js object that your code can use so no issue there.
In the end I chose the straightforward way to recreate all the objects and copy the data. It turned out to be shorter and nicer than I had imagined before. In case it is useful for anyone else, here's how I did it:
data = JSON.parse(file);
a = new lines();
a.height = data.height;
for (var i=0; i<data.lines.length; i++)
{
a.lines.push(new aLine());
a.lines[i].height = data.lines[i].height;
a.lines[i].length = data.lines[i].length;
for (var j=0; j<data.lines[i].dots.length; j++)
{
a.lines[i].dots.push(new aDot());
[... and so on ...]
}
}

Categories