4

I have a problem with parsing JSON to array of object.

I have three JavaScript classes

  1. Pet
  2. Cat extend Pet
  3. Dog extend Pet

I want to create array of Pet objects, then I want to store it in the browser local storage as JSON.

The problem:

When I retrieve the JSON and parse it to array of object, the prototype of the element changed from Cat or Dog, to Object, so when I test

pets[0] instanceof Cat // always false
pets[0] instanceof Dog // always false

Is there I way to keep the prototype of elements as the original not object ?

The classes:

function Pet(imageUrl, name, soundUrl) {
    this.imageUrl = imageUrl;
    this.name = name;
    this.soundUrl = soundUrl;
    this.talk = function() {
    };
}
function Cat(imageUrl, name, soundUrl, favoriteFood) {
    Pet.apply(this,arguments);
    this.favoriteFood=favoriteFood;
}
Cat.prototype=new Pet();
Cat.prototype.constructor = Cat;
function Dog(imageUrl, name, soundUrl, walkingTime) {
    Pet.apply(this,arguments);
    this.walkingTime=walkingTime;
}
Dog.prototype=new Pet();
Dog.prototype.constructor = Dog;

After creating the array I have to save it to the browser local storage

var pets=[];
var cat = new Cat('imageUrl','name','soundUrl','favoriteFood');
pets.push(cat);
localStorage.setItem('pets', JSON.stringify(pets));

To retrieve the array:

        if (localStorage.getItem('pets') !== null)
    {
     var pets = JSON.parse(localStorage.getItem('pets'));
    }
Mohd Alomar
  • 953
  • 1
  • 13
  • 30
  • No because it to long to put the whole code, pets inside another class called HomePage function HomePage(){ this.pets=[]; } – Mohd Alomar May 19 '14 at 13:12

2 Answers2

4

Yes, in JSON you only have plain vanilla objects (and arrays). The only way I can see to deal with this problem is to add an extra property giving the class, then after the parsing of you JSON, you would need to convert the resulting objects into animals (to give them life in a way).

Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
3

An implementation example of @MauricePerry's answer:

You want to add a stringify-method to your Pet class, which returns a vanilla object from which you can instantiate an animal object later on.

Example:

// add stringify function to your Pet class
function Pet(imageUrl, name, soundUrl) {
    ...
    this.stringify = function () {
        var jsonRepresentation = {};
        for (attr in this) {
            if (typeof this[attr] != "function") {
                jsonRepresentation[attr] = this[attr];
            }
        }
        return jsonRepresentation;
    };
};

// add a class property to your various pet subclasses
// e.g. Cat.prototype.class = "cat";

// create an instance of Cat
var cat = new Cat('imageUrl','name','soundUrl','favoriteFood');

// get the info to restore the cat instance later on
var animalInfo = cat.stringify();

/*
cat info would be like:
{
    "class": "cat",
    "imageUrl": "theUrl",
    "name": "theName",
    "soundUrl": "theSoundUrl",
    "favoriteFood": "theFavoriteFood"
}
 */

// then you would store the info to localStorage
...
// later you could retrieve you cat instance like so
var restoredAnimal;
switch(animalInfo.class) {
    case "cat":
        restoredAnimal = new Cat(animalInfo.imageUrl, animalInfo.name, animalInfo.soundUrl, animalInfo.favouriteFood)
        break;
    default:
        console.log('there is no such animal');
}
321hendrik
  • 177
  • 1
  • 8
  • This technique would go well with @MauricePerry's answer. – Katie Kilian May 19 '14 at 13:41
  • @erik.eistee From where you get animalInfo.class because I didn't see property called class is it inherited from Object or should I add it? and if I have to add it why I cant use JSON.stringify() ?? – Mohd Alomar May 19 '14 at 13:52
  • 1
    @MohdAlomarYou want to add a class property to your animal subclasses so you can differentiate later which subclass to instantiate. You could use JSON.stringify, but you with your own stringify method you gain control over which properties you hand over (to maybe have some private properties in a sense). – 321hendrik May 19 '14 at 13:56