user3732793 user3732793 - 2 months ago 6
JSON Question

Store in a file properly after using JSON.stringify

With that piece of code:

function item(name, number){
this.name = name;
this.number = number;
}

var item1 = new item('a',1);
var item2 = new item('b',2);
var box1 = [item1,item2];

console.log(box1);
var box2 = JSON.stringify((box1), null, 2);
console.log(JSON.parse(box2));


I get that output:

[ item { name: 'a', number: 1 }, item { name: 'b', number: 2 } ]
[ { name: 'a', number: 1 }, { name: 'b', number: 2 } ]


What I get with node is the same as the second line when trying to store
box1
in a file with
fs.writeFile(filePath, data,...);
.

Is there a way to get the first one into the json file ?

Answer

The short answer is: not automatically. JSON won't automatically preserve the prototype of objects.

You can do it, but you'll have to handle it yourself with a little code.


Longer answer w/ code

In your first output [ item {} ], the item is Node's way of telling you what the objects prototype is.

Unfortunately, that bit of information is going to get lost when you call JSON.stringify on the object, and all your items are going to become plain objects. So when parsing them back in, Node doesn't know those items are suppose to be created with new item() like they were originally.

One quick way of "preserving" the type would be add a new property into each object that "hints" at what the prototype is suppose to be, and handle that explicitly when parsing back in:

function item(name, number){
    this.name = name;
    this.number = number;

    // prototype hint    
    this._prototype = "item";
}

var item1 = new item('a',1);
var item2 = new item('b',2);
var box1 = [item1,item2];

console.log(box1);
var box2 = JSON.stringify((box1), null, 2);

// now map over the items
var parsed = JSON.parse(box2);
var mapped = parsed.map(function(object) {
  if (object._prototype === "item") {
    return new item(object.name, object.number);
  }
  return object;
});
console.log(mapped);

If you need something more powerful, you could expand on this idea by adding toJSON and fromJSON methods to your item class, and then calling those methods when mapping to<->from JSON.