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

Daniel Einspanjer deinspanjer at gmail.com
Fri Jun 2 17:05:46 UTC 2017


Thanks for the tip!

On Fri, Jun 2, 2017, 12:38 PM Jesse Schulman <jesse at dreamtsoft.com> wrote:

> That's the approach I took too, however I avoided the eval by doing
> bindings.get("Object").newObject() but you should be able to do the same
> thing against the engine if you don't use different bindings.
>
> On Thu, Jun 1, 2017 at 5:32 PM Daniel Einspanjer <deinspanjer at gmail.com>
> wrote:
>
>> Yes, that is the bug.
>>
>> My work around isn't great, I just had to avoid using any form of custom
>> JSObject. Instead, I do an eval('new Object()') to get a holder and put my
>> object and functions inside it via put().
>>
>> -Daniel
>>
>> On Thu, Jun 1, 2017, 6:30 PM Jesse Schulman <jesse at dreamtsoft.com> wrote:
>>
>>> 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