5

My client-side code gets a JSON 'object' from the server, and then parses it. The parsed object contains a 'type' property, which should control the class of the object.

$.getJSON("foo.json").done(function(data, textStatus, xhr) {
    $.each(data.objects, function(key, val)
    {
      if (val.type = "A") // make val into an object of class A, somehow?
        ...
      else if (val.type = "B") // make val into an object of class B somehow?
        ... etc...
    }
}    

How can I create a JavaScript object of the correct type without explicitly copying over each property , or - alternatively - convert the parsed object to a different type?

I've read a little about __proto__ but get the feeling that it's a big sledgehammer for what should be a small nut...

I've seen similar questions regarding Java and Jackson, but nothing for Javascript...

2 Answers 2

5

you could do something like this

function ObjectFactory() {
    this.newInstance = function(val) {
      if (val.type == "A") return new A(val);
      if (val.type == "B") return new B(val);
    }
}    
function A(data) {
    // do something with the data
    this.property = data.property;
}

function B(data) {
    // do something with the data
    this.property = data.property;
    this.bSpecificProperty = data.bSpecificProperty;
}

$.getJSON("foo.json").done(function(data, textStatus, xhr) {
    var objectFactory = new ObjectFactory();
    var objects = $.map(data.objects, objectFactory.newInstance);

    console.log(objects);
}   

if you gave a better example of what the right type was, and some sample data i could provide a better answer.

Sign up to request clarification or add additional context in comments.

2 Comments

Your answer is exactly what I need to do - but I want to avoid all the explicit assignments in the A and B constructors.
I see, so i guess if you merge what i wrote with some _.extend or $.extend. You get what you want. Normally if i was working with data like that i try to be explicit though, because you will probably end up adding methods that read/write against the data. It just feels really brittle if you don't :/, and why not just keep it as a object if you want to do that.
2

You haven't specified what - if any - pattern you are implementing but as another answer has alluded to, you will have to adopt some kind of convention during an object's construction. You don't necessarily have to explicitly account for each type though... and you could also be a little lazy merging your JSON data with $.extend if you are satisfied with it's integrity?

I'd also include a helper function for resolving "types" within a given scope - it's a common practice to namespace objects in a project to avoid polluting the global scope. For example:

function namespace(str, scope){
    scope = scope || window;
    var parts = str.split('.');
    while(parts.length) 
        scope = scope[parts.shift()];
    return scope;
}

Foo = {};
Foo.Bar = function(conf){
    // some kind of constructor
    $.extend(this, conf);
};
// test...
var json = {
    type: 'Foo.Bar',
    var1: 1,
    var2: 2,
    var3: 3
};

var obj = new (namespace(json.type))(json);
console.log(obj, obj instanceof Foo.Bar);

fiddle ... or to fit with your own code:

$.getJSON("foo.json").done(function(data, textStatus, xhr){
    data.objects = $.map(data.objects, function(obj){
        return new (namespace(obj.type))(obj);
    });
});   

1 Comment

$.extend is exactly what I was looking for!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.