We wrap every native JS object into a ScriptObjectMirror for passing back to 
Java. Now, even for the top-level object, you'll just get a ScriptObjectMirror, 
but it happens to implement javax.script.Bindings, which is an interface that 
extends Map<String, Object>.

Unfortunately, we can't subclass ScriptObjectMirror to give you an ArrayMirror 
as no Java class can simultaneously implement both List and Map interfaces due 
to incompatibility in return types of "Object Map.remove(Object)" and "boolean 
List.remove(Object)" :-( Trust me, I was quite mad when I first realized this.

Arguably, we could have a separate ArrayMirror that doesn't subclass 
ScriptObjectMirror (and thus doesn't expose Map interface), just a List 
interface. You'd then lose the ability to treat a JS Array as a Map from the 
Java side -- admittedly, it might be worth it. Got to discuss this a bit more 
with the team.

Attila.

On Nov 27, 2014, at 2:11 PM, Tim Fox <[email protected]> wrote:

> As you know..
> 
> In JS, a JSON Object is represented by a JS object, and in the Java world 
> it's often represented by Map<String, Object>.
> In JS a JSON array is represented by a JS array, and in the Java world it's 
> often represented by a List<Object>.
> 
> I'd love to be able to pass JSON between JS and Java and vice versa with the 
> minimum of performance overhead. This is particularly important in Vert.x as 
> we chuck a lot of JSON around.
> 
> Let's say I have a Java interface which expects some JSON:
> 
> interface SomeInterface {
> 
>    void expectsJSON(Map<String, Object> json);
> }
> 
> Right now I am converting from JS-->Java as follows.
> 
> var someJson = { foo: "bar"};
> String encoded = JSON.stringify(someJson);
> Map<String, Object> map = SomeJavaJSONLibrary.decode(encoded);
> myObject.expectsJSON(map);
> 
> As you can see it's pretty clunky. The other direction is equally as clunky. 
> And it's slow as we're encoding/decoding everything via String.
> 
> Then I realised that if I pass a JS object directly into the expectsJSON 
> method Nashorn will provide me with a Map<String, Object> that backs the 
> original object. I.e. I can do this:
> 
> var someJson = { foo: "bar"};
> myObject.expectsJSON(map);
> 
> Yay! No encoding overhead. Fast. :)
> 
> And it works with nested json:
> 
> var someJson = { foo: "bar", nested: { wibble: "blah"}};
> 
> Just when I was getting my hopes up that this would be a great super fast way 
> of transferring JSON betwen Java and JS, I tried it with a nest array:
> 
> var someJson = { foo: "bar", nestedArray: [123, 456]};
> 
> But in Java, map.get("nestedArray") returns a ScriptObjectMirror not a List 
> as I was hoping. :(
> 
> So.. passing from JS to Java: JS Object maps to Map, but JS Array maps to 
> ScriptObjectMirror. (Seems a bit asymmetric?).
> 
> Any reason why we can't map JS Array to Java list when calling JS->Java? 
> (Perhaps this is related to my previous question backing a JS Array with a 
> List...)
> 
> Do you have any other suggestions for transferring JSON between JS and Java 
> without too much encoding overhead?
> 
> Thanks again!
> 
> 
> 
> 
> 
> 
> 

Reply via email to