Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to "expect" instance of certain Java class in JavaScript code?

Assume that I have Foo.class in Java:

public class Foo {
    public int id;
    public String data;
}

And that I have Foo "class" in JavaScript:

function Foo(id, data) {
    this.id = id;
    this.data = data;
}

Also, assume that I have Java controller that returns instance of Foo.class as a response to a REST request. In my JavaScript (AngularJS) code the request is sent as:

$http.get(url + 'bar/get-foo/')
    .success(function (response) {
        var foo = new Foo(response.id, response.data);
        logger.info("SUCCESS: /get-foo");
    })
    .error(function (error_message) {
        logger.error(error_message)
    });

And it works. But is there a way to avoid passing every property from response to Foo constructor (some sort of expecting the Foo object, or casting it into a Foo object)?

I tried using Object.create(Foo, response) but I get TypeError: Property description must be an object: true

Of course there's always a possibility of refactoring the JavaScript side Foo constructor into:

function Foo(foo) {
    this.id = foo.id;
    this.data = foo.data;
}

But, that would require refactor of large portion of the codebase.

Thanks for your time. I appreciate it!

PS: For those who wonder why do I need this: It's not a problem with small classes like Foo, but some responses are instances of a much larger classes (with over a dozen of fields), which are not under my control.

EDIT: I accepted Chichozell's answer simply because it requires the least amount of work. Robin's and jonnyknowsbest's answers also work, (and will work for pure JavaScript, unlike Chichozell's answer, which is AngularJS specific). Haven't tried Laurentiu L.'s answer, but looks like it should also work. Anyway this is A solution (not THE solution):

.success(function (response) {
    var foo = new Foo();
    angular.extend(foo, response); // angular.merge() for "deep-copy"
    //...
}

Big thanks to everyone who answered/commented/edited in this thread.

like image 221
zkristic Avatar asked Apr 28 '15 07:04

zkristic


2 Answers

If you want to keep your Java thinking on javascript, try using angular.extend(), which will "copy" the properties of an object to another

this = angular.extend(this, response)

In the foo function, or directly on the controler:

 Foo = angular.extend(Foo, response)
like image 174
Cesar Delgado Avatar answered Oct 31 '22 16:10

Cesar Delgado


You can do something like this to "deserialise" the JSON you receive back as the response to an initialised object:

function JSONToObj(jsondata) {
    var json = JSON.parse(jsondata);

    var name = null;
    for(var i in json) { //Use first property as name
        name = i;
        break;
    }

    if (name == null)
        return null;

    var obj = new window[name]();
    for(var i in json[name])
        obj[i] = json[name][i];

    return obj;
}

This assumes that the constructor exists in the global scope and that the response is JSON-formatted as such:

{
    "Foo": {
        "id": "the id",
        "data": "the data"
    }
}
like image 1
Jonathan Smith Avatar answered Oct 31 '22 15:10

Jonathan Smith