Its easy to load JSON into an object in javascript using eval or JSON.parse.
But if you have a proper \"class\" like function, how do you get the JSON data into it?<
Easiest way is to use JSON.parse
to parse your string then pass the object to the function. JSON.parse
is part of the json2 library online.
I;m not too much into this, but aPerson.addAddress should not work, why not assigning into object directly ?
aPerson.address.push(someAddress);
alert(aPerson.address); // alert [object object]
Just in case someone needs it, here is a pure javascript extend function (this would obviously belong into an object definition).
this.extend = function (jsonString){
var obj = JSON.parse(jsonString)
for (var key in obj) {
this[key] = obj[key]
console.log("Set ", key ," to ", obj[key])
}
}
Please don't forget to remove the console.log
:P
A little late to the party, but this might help someone. This is how I've solved it, ES6 syntax:
class Page
{
constructor() {
this.__className = "Page";
}
__initialize() {
// Do whatever initialization you need here.
// We'll use this as a makeshift constructor.
// This method is NOT required, though
}
}
class PageSection
{
constructor() {
this.__className = "PageSection";
}
}
class ObjectRebuilder
{
// We need this so we can instantiate objects from class name strings
static classList() {
return {
Page: Page,
PageSection: PageSection
}
}
// Checks if passed variable is object.
// Returns true for arrays as well, as intended
static isObject(varOrObj) {
return varOrObj !== null && typeof varOrObj === 'object';
}
static restoreObject(obj) {
let newObj = obj;
// At this point we have regular javascript object
// which we got from JSON.parse. First, check if it
// has "__className" property which we defined in the
// constructor of each class
if (obj.hasOwnProperty("__className")) {
let list = ObjectRebuilder.classList();
// Instantiate object of the correct class
newObj = new (list[obj["__className"]]);
// Copy all of current object's properties
// to the newly instantiated object
newObj = Object.assign(newObj, obj);
// Run the makeshift constructor, if the
// new object has one
if (newObj.__initialize === 'function') {
newObj.__initialize();
}
}
// Iterate over all of the properties of the new
// object, and if some of them are objects (or arrays!)
// constructed by JSON.parse, run them through ObjectRebuilder
for (let prop of Object.keys(newObj)) {
if (ObjectRebuilder.isObject(newObj[prop])) {
newObj[prop] = ObjectRebuilder.restoreObject(newObj[prop]);
}
}
return newObj;
}
}
let page = new Page();
let section1 = new PageSection();
let section2 = new PageSection();
page.pageSections = [section1, section2];
let jsonString = JSON.stringify(page);
let restoredPageWithPageSections = ObjectRebuilder.restoreObject(JSON.parse(jsonString));
console.log(restoredPageWithPageSections);
Your page should be restored as an object of class Page
, with array containing 2 objects of class PageSection
. Recursion works all the way to the last object regardless of depth.
@Sean Kinsey's answer helped me get to my solution.
Many frameworks provide an 'extend' function that will copy fields over from one object to another. You can combine this with JSON.parse to do what you want.
newPerson = new Person();
_.extend(newPerson, JSON.parse(aPersonJSON));
If you don't want to include something like underscore you can always copy over just the extend function or write your own.
Coffeescript example because I was bored:
JSONExtend = (obj, json) ->
obj[field] = value for own field, value of JSON.parse json
return obj
class Person
toString: -> "Hi I'm #{@name} and I'm #{@age} years old."
dude = JSONExtend new Person, '{"name":"bob", "age":27}'
console.log dude.toString()
You need to use a reviver
function:
// Registry of types
var Types = {};
function MyClass(foo, bar) {
this._foo = foo;
this._bar = bar;
}
Types.MyClass = MyClass;
MyClass.prototype.getFoo = function() {
return this._foo;
}
// Method which will provide a JSON.stringifiable object
MyClass.prototype.toJSON = function() {
return {
__type: 'MyClass',
foo: this._foo,
bar: this._bar
};
};
// Method that can deserialize JSON into an instance
MyClass.revive = function(data) {
// TODO: do basic validation
return new MyClass(data.foo, data.bar);
};
var instance = new MyClass('blah', 'blah');
// JSON obtained by stringifying an instance
var json = JSON.stringify(instance); // "{"__type":"MyClass","foo":"blah","bar":"blah"}";
var obj = JSON.parse(json, function(key, value) {
return key === '' && value.hasOwnProperty('__type')
? Types[value.__type].revive(value)
: this[key];
});
obj.getFoo(); // blah
No other way really...