Is there a way to “expect” an instance of a particular Java class in JavaScript code?

Suppose I have Foo.class in Java:

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

And that I have a Foo "class" in JavaScript:

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

Also suppose I have a Java controller that returns an instance of Foo.class in 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 any way to avoid passing each property from the response to the Foo constructor (some kind of waiting for the Foo object or its inclusion in the Foo object)?

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

Of course, there is always the option of refactoring the constructor with JavaScript Foo:

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

But this will require refactoring a large part of the code base.

Thank you for your time. I appreciate it!

PS: For those who wonder why I need it: this is not a problem with small classes like Foo, but some answers are examples of much larger classes (with more than a dozen fields) that are not under my control.

EDIT: I made Chichozell's decision simply because it requires the least amount of work. The Robin and jonnyknowsbest answers also work (and will work in pure JavaScript, unlike the Chichozell answer, which is specific to AngularJS). Did not try Laurentiu L. to answer, but it seems that it should work too. In any case, this is a solution (not a solution):

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

Many thanks to everyone who replied / commented / edited this topic.

+8
java javascript casting angularjs
source share
4 answers

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

 this = angular.extend(this, response) 

In the foo function or directly on the controller:

  Foo = angular.extend(Foo, response) 
+1
source share

You can do something like this to "deserialize" the JSON you received back as a response to the initialized 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; } 

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

 { "Foo": { "id": "the id", "data": "the data" } } 
+1
source share

You can also do something like this jsFiddle to achieve the structure you are describing. The createObject couold function looks something like this: a piece of code.

 function createObject(response, toCreate){ var newObject = new toCreate(); for(var attr in response){ if(newObject.hasOwnProperty(attr)){ newObject[attr] = response[attr]; } } return newObject; } 

If you have createObject that takes a js object with the same attributes as your function as a response parameter, and a function (the object you want to create) as the toCreate parameter.

See the output from the jsFiddle console log and you will see that it works.

You can also, as seen from jsFiddle, remove check for hasOwnProperty to set all attributes from the response, regardless of whether the javascript function is defined.

+1
source share

You can make it pretty versatile if you want. And there will not be too much refactoring, and this decision will facilitate your future changes for both classes.

You can change your Foo javascript object to an Angular JS service and enter it where you need it. Thus, your data is available all over the world. This is better than the local variable foo.

 yourApp.factory('Foo', function () { //set a default or just initialize it var fooObject= {}; return { getId: function () { return fooObject.id; }, getData: function() { return fooObject.data;}, setId: function(newId){fooObject.id = newId}, setData: function(newData){fooObject.data=newData;}, initializeFromObject : function(response){ for (var prop in response){ fooObject[prop] = response[prop]; } } }; } ); 

You can also make creating new services more secure by using methods like hasAllProperties (by iterating through the properties of an object, whether it be an array or an object) .; hasNullValues ​​etc.

We hope this helps, and you will see its value.

+1
source share

All Articles