How to properly implement JSObject to provide conversion of Gson JsonElement objects?

Jesse Schulman jesse at dreamtsoft.com
Thu Jun 1 22:30:01 UTC 2017


Ironically, I'm hitting a similar issue with a library doing an
Object.keys() call against a custom JSObject, can you share the solution
you've taken?

Also, I'm guessing this is the RFE you created:
https://bugs.openjdk.java.net/browse/JDK-8181203?jql=text%20~%20%22Object.keys%20nashorn%22

Thanks!
Jesse

On Tue, May 30, 2017 at 9:34 AM Daniel Einspanjer <deinspanjer at gmail.com>
wrote:

> Thank you, yes that is very similar to the approach I went down.
> Ultimately I hit another roadblock that forced me to approach the entire
> issue differently.  The JS library I am interacting with uses Object.keys()
> and currently, Nashorn doesn't support Object.keys() calls with custom
> JSObjects.  I filed an RFE for that, but due to the issue, I'm having to
> avoid using JSObject entirely.
>
> Thanks again for your reply.
>
> -Daniel
>
> On Tue, May 30, 2017 at 12:29 PM Jesse Schulman <jesse at dreamtsoft.com>
> wrote:
>
>> If you haven't got this working yet, one possible solution is to return
>> anonymous inner AbstractJSObject that returns true for isFunction calls:
>>
>>    public Object getMember(String name) {
>>       if ("map".equals(name)) {
>>          return new AbstractJSObject() {
>>             @Override
>>             public Object call(Object thiz, Object... args) {
>>                // delegate to your JsonArray.map method from this
>> annonymous inner class
>>                // in your example nashorn should pass you a single
>> instance of ScriptObjectMirror for args that returns true for isFunction()
>> call
>>             }
>>
>>             @Override
>>             public boolean isFunction() {
>>                   return true;
>>             }
>>          };
>>       }
>>
>>       return null;
>>    }
>>
>>
>> Hope that helps!
>> Jesse
>>
>> On Thu, May 25, 2017 at 1:11 PM Daniel Einspanjer <deinspanjer at gmail.com>
>> wrote:
>>
>>> I have a project that makes extensive use of the Google Gson library.
>>>
>>> In this particular case, I have a JsonArray object (which implements
>>> iterable) containing a collection of objects.  In pure JSON it would look
>>> like this:
>>>
>>> [ 1, true, {"a": "b"}, [1,2] ]
>>>
>>> In Gson JsonElements, it looks like this:
>>>
>>> arr = new JsonArray();
>>> arr.add(1);
>>> arr.add(true);
>>>
>>> obj = new JsonObject();
>>> obj.addProperty("a", "b");
>>>
>>> arr.add(obj);
>>>
>>> innerArr = new JsonArray();
>>> innerArr.add(1);
>>> innerArr.add(2);
>>>
>>> arr.add(innerArr);
>>>
>>> I am calling a Javascript function in Nashorn that is trying to do a map
>>> over this array:
>>>
>>> nash.eval("function doIt(arr) { print(arr.map(function(item) { return
>>> (typeof item); })); }");
>>>
>>> So, in order for this to work with my own arbitrary object (JsonArray), I
>>> believe I need to implement JSObject.
>>>
>>> I created the wrapper class that implements it, using the underlying
>>> JsonArray object as a delegate.  things like isArray() and such are
>>> trivial, but I'm having trouble with the map.
>>> I have a map method that takes a functional interface which is available
>>> for the JsonArray object.
>>>
>>> Nashorn calls getMember("map") when the doIt function is executed.  I
>>> cannot figure out how to give it an appropriate function reference to my
>>> JsonArray.map method.
>>> I was able to handle getMember("toString") easily enough, but the problem
>>> is that method doesn't take any arguments, so returning a simple
>>> Callable<Object> is fine for it, but map is going to take arguments that
>>> I
>>> don't know about ahead of time.
>>>
>>> I would really appreciate some assistance here.  Thanks.
>>>
>>> -Daniel
>>>
>>


More information about the nashorn-dev mailing list