0

Update: I was wrong naming a plain JavaScript object as "JSON object". Thanks to guys who pointed it out in comments below. So I edited the question to avoid further misunderstanding.

I wonder whether calling JavaScript function with JavaScript object (that can be described as JSON string) as an argument using netscape.javascript.JSObject is possible from Java. I tried the following code snippet:

JSObject.getWindow(MyApplet.this).call(jsFunctionName, jsArgs);

According to this article Java objects are passed to named JavaScript function as is and will be automatically converted to some JavaScript primitives depending on context they are used in. Does it mean that it is impossible to pass a real JavaScript object described as some JSON string to JavaScript function and I have to look for a workaround like preparing a JSON string as java.lang.String argument in Java and then parsing it in JavaScript function to get a plain JavaScript object?

Timofey Gorshkov
  • 4,987
  • 6
  • 41
  • 66
ezze
  • 3,933
  • 2
  • 34
  • 58
  • 5
    There in no such thing as a JSON object. You probably mean a JavaScript object. – ThiefMaster Oct 09 '12 at 15:38
  • 1
    @ThiefMaster I think he mean passing an object of JSObject class in Java to a javascript function. – gigadot Oct 09 '12 at 15:41
  • Forgive me, guys, if I am indistinct. I mean JSON we usually deal with in JavaScript, something like this { 'name': "Peter", 'favoriteLanguages': ['java', 'javascript'] }. I want to have it in my JavaScript function as an argument passed from Java. Seems to me that I can only pass a java.lang.String and then parse it to JSON in JavaScript function in a string context. – ezze Oct 09 '12 at 15:49
  • 1
    @Ezze: JSON is a *string* *serialisation* of [plain] objects (which looks like JavaScript literals). What exactly do you want to pass, objects or encoded strings? – Bergi Oct 09 '12 at 15:56
  • 1
    @Bergi: I want to pass objects and work with them as with JavaScript objects as ThiefMaster mentioned above. – ezze Oct 09 '12 at 16:02

1 Answers1

2

It is better to refer to chapter: «19.3 LiveConnect Data Conversion».

Every object passed within jsArgs is wrapped with JavaObject wrapper. In fact it is the same JavaScript object with all public properties and methods of underlying object available.


E.g. if I have folowing Java class:

public class MyJavaClass {
    public String name;
    public int number;
    public MyJavaClass(String n, int i) {
        name = n;
        number = num;
    }
}

And call JavaScript function:

JSObject.getWindow(MyApplet.this).call("abFunc", new MyJavaClass("Kolya", 500));

JavaScript function could look like:

var abFunc = function(obj){
    numberPlusThousand = (1000 + obj.number);
    name = String(obj.name);
    ...
};

And you could convert it to JSON string like any other JavaScript object, if you want.


Instances of JSObject class passed as arguments to call function will be converted to corresponding JavaScript objects. So, if you want to avoid JavaObject instaces occurence in your JavaScript code, you could try to create new JSObject instances like this:

JSObject myJsObj = (JSObject) JSObject.eval("{}");

And add new properties:

myJsObj.setMember("name", JSObject.eval("'Kolya'"));
myJsObj.setMember("number", 500);

Or like this:

myJsObj.eval("self.name = 'Kolya'");
myJsObj.eval("self.number = 500");

To my mind, it will be more convenient to represent JavaScript objects within Java as maps, pass them to JavaScript as JSON strings using library like Gson, and convert them to JavaScript objects using JSON.parse().

Take a look at this Gson usage:

Map m1 = ImmutableMap.of("id", "Kolya", "num", 500);
Map m2 = ImmutableMap.of("marks", new byte[] {5, 4, 5, 3});
Map m = ImmutableMap.of("m1", m1, "m2", m2, "l", ImmutableList.of("str", 234L, false));
System.out.println(new Gson().toJson(m));
// {"m1":{"id":"Kolya","num":500},"m2":{"marks":[5,4,5,3]},"l":["str",234,false]}

ImmutableMap and ImmutableList are from Guava libraries.

Community
  • 1
  • 1
Timofey Gorshkov
  • 4,987
  • 6
  • 41
  • 66
  • I see that I can access public members of Java class within JavaScript function but a set of properties I want to pass to this one may differ depending on some conditions. So I need to create a separate Java class for each combination of properties or to create one big class that contains all possible properties where most of them will be not set for each particular case. That's why I would prefer to describe an object I want to pass to JavaScript function as JSON string. – ezze Oct 09 '12 at 19:37
  • 1
    Of course, I also can convert a set of Java class' properties to JSON string in JavaScript function but I wonder whether it's possible to have a JavaScript object passed to function as argument (`obj` in your example above) without any need in further conversions. – ezze Oct 09 '12 at 19:55
  • eval() method of JSObject is what I needed. A callback function will deal with JavaScript object in the beginning of its execution and calling JSON.parse() will not be required then. I know that using eval() should be avoided but it's guaranteed that eval() will work with a valid JSON string in my case. – ezze Oct 10 '12 at 17:38
  • javaObject wrapper!!, I was working with applets for a long and I never realised that the return java objects to js object has the equivalent java methods (I was always returning strings...). +1! – albciff Oct 15 '14 at 09:12