Also, the documentation for both List and Map interfaces prescribes an exact 
algorithm[1][2] that every implementation of them must use to calculate their 
hashCode(), and they too are incompatible. This is not as insurmountable as a 
javac error, but still not a good idea to violate. FWIW, having a separate 
ArrayMirror that implements only List<Object> might still be workable.

Attila.

---
[1] http://docs.oracle.com/javase/8/docs/api/java/util/List.html#hashCode--
[2] http://docs.oracle.com/javase/8/docs/api/java/util/Map.html#hashCode--

On Nov 27, 2014, at 2:40 PM, Attila Szegedi <[email protected]> wrote:

> [...]
> 
> 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.
> 
> [...]
> 
> 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