0

I have seen examples of how to do this that rely heavily on the browser environment but not examples that work in the native node.js environment.

I need to cast JSON objects to javascript classes of a type that does not yet exist but is given by an input string.

I found some nice code on stackoverflow to retype JSON to known class but I have not figured out how to do this when the class type is a string and the class does not exist.

In software terms I need to:

var className = 'Bar'; 
console.log(global[className]); // false - class Bar is not defined
var jsonIn = '{ "name": "Jason" }';
var retypedJson = retypeJSON(jsonIn, className);
console.log(retypedJson instanceof Bar)      // true

The code for recasting JSON. (Nice as it doesn't call eval or explicitly copy property names.)

// define a class
var Foo = function(name) {
  this.name = name;
}
// make a method
Foo.prototype.shout = function() {
  console.log("I am " + this.name);
}
// make a simple object from JSON:
var x = JSON.parse('{ "name": "Jason" }');
// force its class to be Foo
x.__proto__ = Foo.prototype;
// the method works
x.shout();
console.log(x instanceof Foo); // true

Thanks!

20
  • Do you know the object Bar? How do you create it? What if the input is none of the object you know? Commented Sep 25, 2014 at 8:44
  • @DrakaSAN Bar is a completely new class. The question is how to create it from a variable storing the string 'Bar'. Commented Sep 25, 2014 at 8:54
  • 3
    javascript doesn't have classes. Commented Sep 25, 2014 at 8:57
  • @Colin: How do you define which property have the object? In the string? What form? Commented Sep 25, 2014 at 8:58
  • 1
    @Colin instanceof just checks if Foo.prototype is in object prototype chain Commented Sep 25, 2014 at 9:14

2 Answers 2

0

I have an answer that makes some use of eval and __proto__. Eval is only used to create the first prototype.

// create prototype - called once
var on = 'Apple';
var estr = 'function ' + on + '() {} ' + on + '.prototype.getInfo = function() { return this.name; }; ';
eval.apply(global, [estr]);

// make a simple object from JSON:
// called many times 
var apl = JSON.parse('{ "name": "Jason" }');

// force its class to be Foo
apl.__proto__ = global[on].prototype;

// this method works
console.log(apl.getInfo());
Sign up to request clarification or add additional context in comments.

5 Comments

eval.apply is rubbish. Also, there's no reason to pollute the global namespace - and depending on where your on string comes from, this even might be a monstrous security issue.
@Bergi AOK. Do you have a better solution?
Why not just do apl.getInfo = function() { return this.name; }; (maybe caching the function)? Even if you want to use __proto__ for whatever reasons, I don't see any reason to create empty constructors, or even use eval to do so.
@Bargi I don't see how apl.getInfo = function() { return this.name; }; forces the object name. I.e., in the example I need to define a prototype with the name in var on;, in this case Apple.
"Object names" as you call them are quite insignificant anyway, no program code would depend on them. Sure, to get a named function you need to eval some code, but the function doesn't need to be in global scope for that.
0

Maybe this?

var constructors = {
   "Obj1": ObjConstructor1(){},
   "Obj2": ObjConstructor2(){},
}
var obj = new constructors.Obj1();
var jsonObj = {"a":1,"b":2};

for (var x in jsonObj) {
  obj[x] = jsonObj[x];
}

1 Comment

This may work. Can you call the constructor if the name of the 'class' were in a string? (without using a switch statement)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.