Setting and getting object to local storage using stringify? - javascript

Creating an object called car:
function car(temp){
this.brand=temp[0];
this.color=temp[1];
this.year=temp[2];
}
var temp = ['Skoda', 'Red', '2012'];
car = new car(temp);
Setting object and stringify after reading from localStorage:
localStorage.setItem('car',car);
car = localStorage.getItem('car');
car = JSON.stringify(car);
car after stringify-----------------> [object Object] at file:///android_asset/www/...
Stringify object and Setting object to localStorage after it:
localStorage.setItem('car',JSON.stringify(car));
car = localStorage.getItem('car');
car after stringify-----------------> "{\"brand\":\"Skoda\",\"color\":\"Red\",\"year\":\"2012\"}" at file:///android_asset/www/...
Question 1: Why does it make difference what is the order when you stringify the object?
Question 2: Why can't I use stringified object like that:
08-21 11:49:14.860: I/Web Console(9642): car after stringify-----------------> {"brand":"Skoda","color":"Red","year":"2012"}
console.log("car.brand----->" +car.brand);
car.name----->undefined

From my understanding you can't use your stringified object once it's been stringified because it's no longer an object. It's a String.
So when you try to do car.brand on the string there is no property brand.
Personally, good practice in my opinion would be to do.
function car(temp){
this.brand=temp[0];
this.color=temp[1];
this.year=temp[2];
}
var temp = ['Skoda', 'Red', '2012'];
car = new car(temp);
localStorage.setItem('car',JSON.stringify(car));
car = localStorage.getItem('car');
car = JSON.parse(car);
This means the car object is now not a string but an object.
When doing this also write to local storage using stringify and read using parse.

You can't store JavaScript object is localStorage, see this question.
So use your second option. First stringify the object the store it. And later pick it up and parse it to a javascript object.
localStorage.setItem('car',JSON.stringify(car));
carString = localStorage.getItem('car');
car = JSON.parse(carString);
console.log(car.brand); // Skoda

I was facing this same issue recently. Check out this script I wrote.
https://github.com/andresgallo/truStorage
It allows storage and retrieval of objects inside local storage. It will return objects as objects automatically if need be. The other thing is you also set and get items in a nested object. Best part of it all is that its a tiny script.

The latest browsers now support localStorage as objects natively. I have tested this with Chrome v44 and Firefox v34:
localStorage
Storage {debug: "undefined", uid: "3", length: 2}
typeof localStorage
"object"
So from now on. You'll be alright.

Related

Meteor Session variable not storing array

I'm working on a project with search option filters and they're updated via sessions, but I'm having some issues with the session variable actually taking the array. It works fine for non-array based values, but for instance when I pass an array with RegExp objects to be used in a mongo $in selector it doesn't work as expected. The functions work fine right up until it hits Session.set() in the code snippet below so I know I have to be doing something wrong with that:
Option.prototype.update = function () {
//updates session variable if static option
if (!this.isDynamic) {
if(Object.prototype.toString.call(this.value) === '[object Array]') {
var temp = this.value.slice(0);
Session.set(this.optionName, temp);
console.log(Session.get(this.optionName));
}
else {
Session.set(this.optionName, this.value);
}
};
};
for whatever reason instead of displaying the array with values in it, it displays
[Object], and the object in that array is empty. I've read the other Overflow posts on Session variables and arrays, and simply cloning the array before passing it doesn't seem to be working. Any idea what I'm doing wrong?
Your code is correct (although slightly convoluted). The problem is that Session only takes EJSON–able values, and regexes are not EJSON–able. From the perspective of EJSON, regex looks just like an empty object, and that's exactly what you get in the stored array. Similar problem would appear if you try to store object with custom prototype, or with private (not enumerable) properties: everything that is not serialized to EJSON is lost.
The solution here is to create your own serialization method that will work with regexes. For example, if you will always have a flat array of regexes, you could simply stringify them before storing:
var temp = _.map(this.value, function(regex) {
return regex.toString();
});

What's the fastest way to get all the initial values of a variable? JS

I want to get the initial values (What I first defined it to be) of all the properties for one of my objects.
I want to do this at the "end" of my game.
I could just copy and paste the properties but the object is pretty big and im wondering if this would slow the site down a bit?
Thanks!
Code example:
var MyObject = {
nestedObject1 : {
//...
},
nestedObject2 : {
value1 : "Hi",
value2 : 1
},
objectProperty : 2637
}
How would I get all (Or maybe excluding one of the nested objects) of the properties to their intial value?
I don't quite fully understand how you want to get the initial values, at the end of your running. But probably the easiest way to do this is to just serialize your object to JSON using JSON.stringify.
var original = JSON.stringify(myObject)
Then at the end of your application when you want access to this original object again you can rehydrate it to a new JavaScript object:
original = JSON.parse(original);

localStorage array of objects handling

Array of JSON objects are stored in HTML5 localStorage.
For now delimiter is ;
For accessing and modifying array of objects from localStorage, split(';') and join(';') operations used.
However ,delimiter approach looks unstable.
For instance ; could be met inside objects attribute and split(';') operation will be uncorrect.
It could be used ;; for delimiter,but i'm not certain it will be stable also.
Is there any robust way to handle localStorage presented as array of objects,as far localStorage saved as String?
EDIT
one of stoppers is that array of object couldn't be saved to localStorage as classical: "[{},{}]"
localStorage converts it automatially to String like "{},{}"
my current data within localStorage:
"{"name":"volvo","id":"033"};{"name":"saab","id":"034"}"
assumption
perhaps,i can add [ at the start and ] at the end,but it looks not gracefull
Just convert the objects to JSON strings:
localStorage.setItem("savedData", JSON.stringify(objects));
And vice versa:
objects = JSON.parse(localStorage.getItem("savedData")));
Or you can add multiple objects in the same localStorage value:
localStorage.setItem("savedData", JSON.stringify([object1, object2 /*, etc*/]));
object1 = JSON.parse(localStorage.getItem("savedData"))[0];
object2 = JSON.parse(localStorage.getItem("savedData"))[1];
Here's the DOM storage specification.
You can also access savedData like this:
localStorage.savedData = "Hello world"
var foo = localStorage.savedData;
This can be used for both getting and setting the data, but it is considered less "safe" than getItem('name'); and setItem('name', 'value');
Read variables:
var xyz = JSON.parse( localStorage.getItem( 'element' ) );
Store variables:
localStorage.setItem( 'element' , JSON.stringify(xyz));
where element is the name of the local storage variable and xyz the name of the js variable.

Javascript pushing objects into array changes entire array

I'm using a specific game making framework but I think the question applies to javascript
I was trying to make a narration script so the player can see "The orc hits you." at the bottom of his screen. I wanted to show the last 4 messages at one time and possibly allow the player to look back to see 30-50 messages in a log if they want. To do this I set up and object and an array to push the objects into.
So I set up some variables like this initially...
servermessage: {"color1":"yellow", "color2":"white", "message1":"", "message2":""},
servermessagelist: new Array(),
and when I use this command (below) multiple times with different data called by an event by manipulating servermessage.color1 ... .message1 etc...
servermessagelist.push(servermessage)
it overwrites the entire array with copies of that data... any idea why or what I can do about it.
So if I push color1 "RED" and message1 "Rover".. the data is correct then if I push
color1"yellow" and message1 "Bus" the data is two copies of .color1:"yellow" .message1:"Bus"
When you push servermessage into servermessagelist you're really (more or less) pushing a reference to that object. So any changes made to servermessage are reflected everywhere you have a reference to it. It sounds like what you want to do is push a clone of the object into the list.
Declare a function as follows:
function cloneMessage(servermessage) {
var clone ={};
for( var key in servermessage ){
if(servermessage.hasOwnProperty(key)) //ensure not adding inherited props
clone[key]=servermessage[key];
}
return clone;
}
Then everytime you want to push a message into the list do:
servermessagelist.push( cloneMessage(servermessage) );
When you add the object to the array, it's only a reference to the object that is added. The object is not copied by adding it to the array. So, when you later change the object and add it to the array again, you just have an array with several references to the same object.
Create a new object for each addition to the array:
servermessage = {"color1":"yellow", "color2":"white", "message1":"", "message2":""};
servermessagelist.push(servermessage);
servermessage = {"color1":"green", "color2":"red", "message1":"", "message2":"nice work"};
servermessagelist.push(servermessage);
There are two ways to use deep copy the object before pushing it into the array.
1. create new object by object method and then push it.
servermessagelist = [];
servermessagelist.push(Object.assign({}, servermessage));
Create an new reference of object by JSON stringigy method and push it with parse method.
servermessagelist = [];
servermessagelist.push(JSON.parse(JSON.stringify(servermessage));
This method is useful for nested objects.
servermessagelist: new Array() empties the array every time it's executed. Only execute that code once when you originally initialize the array.
I also had same issue. I had bit complex object that I was pushing in to the array. What I did; I Convert JSON object as String using JSON.stringify() and push in to the Array.
When it is returning from the array I just convert that String to JSON object using JSON.parse().
This is working fine for me though it is bit far more round solution.
Post here If you guys having alternative options
I do not know why a JSON way of doing this has not been suggested yet.
You can first stringify the object and then parse it again to get a copy of the object.
let uniqueArr = [];
let referencesArr = [];
let obj = {a: 1, b:2};
uniqueArr.push(JSON.parse(JSON.stringify(obj)));
referencesArr.push(obj);
obj.a = 3;
obj.c = 5;
uniqueArr.push(JSON.parse(JSON.stringify(obj)));
referencesArr.push(obj);
//You can see the differences in the console logs
console.log(uniqueArr);
console.log(referencesArr);
This solution also work on the object containing nested keys.
Before pushing, stringify the obj by
JSON.stringify(obj)
And when you are using, parse by
JSON.parse(obj);
As mentioned multiple times above, the easiest way of doing this would be making it a string and converting it back to JSON Object.
this.<JSONObjectArray>.push(JSON.parse(JSON.stringify(<JSONObject>)));
Works like a charm.

Deserializing JavaScript object instance

I am working on an app that heavily uses JavaScript. I am attempting to include some object-oriented practices. In this attempt, I have created a basic class like such:
function Item() { this.init(); }
Item.prototype = {
init: function () {
this.data = {
id: 0,
name: "",
description: ""
}
},
save: function() {
alert("Saving...");
$.ajax({
url: getUrl(),
type: "POST",
data: JSON.stringify(this.data),
contentType: "application/json"
});
}
}
I am creating Item instances in my app and then saving them to local storage like such:
Item item = new Item();
window.localStorage.setItem("itemKey", JSON.stringify(item));
On another page, or at another time, I am retriving that item from local storage like such:
var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
Unfortunately, the "save" function does not seem to get reached. In the console window, there is an error that says:
*save_Click
(anonymous function)
onclick*
I have a hunch that the "(anonymous function)" is the console window's way of saying "calling item.save(), but item is an anonymous type, so I am trying to access an anonymous function". My problem is, I'm not sure how to convert "var item" into an Item class instance again. Can someone please show me?
Short answer:
Functions cannot be serialized into JSON.
Explanation:
JSON is a cross-platform serialization scheme based on a subset of JS literal syntax. This being the case, it can only store certain things. Per http://www.json.org/ :
Objects: An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
Arrays: An array is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
values: A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.
Functions cannot be serialized into JSON because another non-JS platform would not be able to unserialize and use it. Consider the example in reverse. Say I had a PHP object at my server which contained properties and methods. If I serialized that object with PHP's json_encode() and methods were included in the output, how would my JavaScript ever be able to parse and understand PHP code in the methods, let alone use those methods?
What you are seeing in your resulting JSON is the toString() value of the function on the platform you're using. The JSON serilizer calls toString() on anything being serialized which isn't proper for JSON.
I believe your solution is to stop storing instances in JSON/local storage. Rather, save pertinent data for an instance which you set back to a new instance when you need.
I know this question is answered already, however I stumbled upon this by accident and wanted to share a solution to this problem, if anyone is interested.
instead of doing this:
var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
do something like this:
// get serialized JSON
var itemData = window.localStorage.getItem("itemKey");
//instantiate new Item object
var item = new Item();
// extend item with data
$.extend(item, JSON.parse(itemData));
// this should now work
item.save();
this will work so long as the function you are wanting to call (ie, save()) is prototypal and not an instance method (often times the case, and is indeed the case in the OP's original question.
the $.extend method is a utility method of jquery, but it is trivial to roll your own.
You cant do that, how can javascript possibly knows that item have a save function ? json doesnt allow functions as datas. just read the json spec , you cant save functions.
what you need to do is to create a serialize and deserialize method in the hash you want to stock. that will specifiy what to export and how you can "wake up" an object after parsing the corresponding json string.
You can only store plain Objects in DOMstorages (cookies, urlparams..., everything that needs [de]serialisation through JSON.stringify/JSON.parse). So what you did when sending the ajax data
ajaxsend(this.data);
also applies to string serialisation. You can only store the data, not the instance attributes (like prototype, constructor etc.). So use
savestring(JSON.stringify(item.data));
which is possible because item.data is such a plain Object. And when restoring it, you will only get that plain data Object back. In your case it's easy to reconstruct a Item instance from plain data, because your Items hold their values (only) in a public available property:
var item = new Item;
item.data = JSON.parse(getjsonstring());
Disclaimer
Not a full time time J.S. Developer, answer may have some minor bugs:
Long Boring Explanation
As mentioned by #JAAulde, your object cannot be serialized into JSON, because has functions, the technique that you are using doesn't allow it.
Many people forget or ignore that the objects that are used in an application, may not be exactly the same as saved / restored from storage.
Short & quick Answer
Since you already encapsulate the data members of your object into a single field,
you may want to try something like this:
// create J.S. object from prototype
Item item = new Item();
// assign values as you app. logic requires
item.data.name = "John Doe";
item.data.description = "Cool developer, office ladies, love him";
// encoded item into a JSON style string, not stored yet
var encodedItem = JSON.stringify(item.data)
// store string as a JSON string
window.localStorage.setItem("itemKey", encodedItem);
// do several stuff
// recover item from storage as JSON encoded string
var encodedItem = window.localStorage.getItem("itemKey");
// transform into J.S. object
item.data = JSON.parse(encodedItem);
// do other stuff
Cheers.

Categories

Resources