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 ...]
}
}
Related
I am using IBM BPM 8.6
I have an input string as follows:
"\"RECORD_CONTACT\":\"Maram\" , \"DRUG\":\"Panadol\"
In a script on server side, I want to dynamically create a business object like this:
tw.local.recordContact = Maram;
tw.local.drug = Panadol;
How can I dynamically create the business object?
There are a few problems with your request. The first is that you are not creating a business object, you are creating variables. In IBM BPM the variables have to be declared at design time or you will get an error, so invoking attempting to call something like -
tw.local.myVariable = 'Bob';
Will throw an exception if tw.local.myVariable has not been declared. Base on your other question you asked here (link), I'm going to assume you actually have an ANY variable declared called "return" so that
tw.local.return.myVariable = 'Bob'
will work. Given that I based on Sven's answer I think something like the following will work (you will need to validate)
var str = "\"RECORD_CONTACT\":\"Maram\" , \"DRUG\":\"Panadol\"";
var jsonStr = "{" + str.replace(/\\\"/g,'\"') + "}";
var tempValue = JSON.parse(jsonStr);
var keyArray = Object.keys(tempValue);
var valueArray = Object.values(tempValue);
for(var keyCount=0; keyCount<keyArray.length; keyCount++{
var evalString = "tw.local.return."+keyArray[keyCount]+"="+valueArray[keyCount];
eval(evalString);
}
I'll note that doing this is a very bad idea as it would be very brittle code and that using eval() in this manner opens you up to all sorts of possible exploits. It will also fail badly if the value for one of the keys is not a simple type.
-Andrew Paier
One should know what you are going to do with dynamically created Business Objects (BO) to answer you better. Like a very generic way would be - creating JSON object instead of BO.
But if you want to stick with BO then this is only possible when you know all the BO structure (schema) beforehand during design time.
var str = "\"RECORD_CONTACT\":\"Maram\" , \"DRUG\":\"Panadol\"";
vat objArray = str.split("reg ex to split each object string")
foreach (obj in objArray ){
if(obj.indexOf( "RECORD_CONTACT")!=-1)
tw.local.recordContact = new tw.object.RECORD_CONTACT();
//below goes code get value of each attribute of BPM from string
}
else if(obj.indexOf( "DRUG")!=-1){
//similar code to create BO DRUG
}
Don't forget to create BO before using those :)
I am calling an API which is giving me back, among other things, an array of javascript objects. The objects in the array are named and I need to use the name in the new individual objects I am creating from the array. Problem is, I don't know how to get to the object's name.
{
"OldCrowMine.E9001":{"last_share":1524883404,"score":"0.0","alive":false,"shares":0,"hashrate":0},
"OldCrowMine.S9001":{"last_share":1524,"score":"648.24","alive":true,"shares":632,"hashrate":14317274},
}
I am after the "OldCrowMine.E9001" bit. I am sure this is quite simple, I just don't know how to search for the answer because I am not sure what to call this. I have tried searching for a solution.
Just loop - or am I missing something? Simplified raw data version.
var raw = {
"OldCrowMine.E9001":{"share":1524883404},
"OldCrowMine.S9001":{"share":1524}
};
for(var first in raw) {
console.log(first +" share -> "+ raw[first]["share"]);
}
var obj = {
"OldCrowMine.E9001":{"last_share":1524883404,"score":"0.0","alive":false,"shares":0,"hashrate":0},
"OldCrowMine.S9001":{"last_share":1524,"score":"648.24","alive":true,"shares":632,"hashrate":14317274},
}
console.log(Object.keys(obj)[0]);
Get the keys and map the name and the object:
var x= {
"OldCrowMine.E9001":{"last_share":1524883404,"score":"0.0","alive":false,"shares":0,"hashrate":0},
"OldCrowMine.S9001":{"last_share":1524,"score":"648.24","alive":true,"shares":632,"hashrate":14317274},
};
var mapped = Object.keys(x).map(function(d,i){return [d,x[d]]});
The name is map[n][0] and its object is map[n][1] where n is your item number.
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);
}
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.
I am creating a gallery plug-in in which I need to figure out the number of elements in a plain javascript object. The following is how I would like to be able to create the gallery.
$.Gallery.create($('#galContainer'), {
'img1.png': 'http://linktosomewhere/',
'img2.png': 'http://linktosomewhere/',
'img3.png': 'http://linktosomewhere/',
........
}, optionsObj);
This will put the images into the gallery with the corresponding links to some page when clicked. Currently I am using an array for that second parameter without the links and I am getting the length of the images using images.length. However using the notation above would be ideal for me and I need to be able to tell how many keys there are in this object.
I am aware of this post and a few others saying you can not get the number of elements in the object. If this is indeed the case, do you have any suggestions on another way to setup this function call which will be efficient and easy to use?
The code you see in the other question you linked to is really the only way to do it. Here's how you can create a function to do it:
function count(obj) {
var i = 0;
for (var x in obj)
if (obj.hasOwnProperty(x))
i++;
return i;
}
Can't you use an array of objects instead?
$.Gallery.create($('#galContainer'), [
{src:'img1.png', href:'http://linktosomewhere/'},
{src:'img2.png', href:'http://linktosomewhere/'},
{src:'img3.png', href:'http://linktosomewhere/'},
........
], optionsObj);
You should just add a .src and .href in your code to read it.
The way you designed your dataset as a simple hash is not very flexible for additional attributes(size, categories, selected, etc...)
Underscore.js has a method that will tell you how large the object is _.size(obj);
Object.prototype.count = function()
{
var c = 0;var i;
for(i in this){if (this.hasOwnProperty(i)){c++;}};
return c;
}
Personally I would build your own prototype for Object, you can use MyObject.length but I think its not fully supported by IE.
test reveal that the length variable is unavailable in Objects.
Testcase:
MyObject = {
a : '0',
b : '1',
c : '2'
}
if(MyObject.count() > 5)
{
$.Gellery.Error('Images','Only 5 images allowed'); //...
}
http://jsfiddle.net/b9Nwv/