访问 java 地图和地图Rhino 中的列表为 JavaScript 对象

发布于 2024-11-08 12:42:02 字数 467 浏览 5 评论 0原文

有没有办法在 Rhino 中以 JavaScript 对象的形式访问 Java 地图和列表?

我有一个 Map,其中仅包含其他映射以及基元和字符串列表,我想将其传递给 Rhino 脚本并对其执行操作,并将修改后的对象返回到 Java - 但因为它们是 java.util .Map 和 java.util.List 对象,我无法使用标准 JavaScript 关联数组语法。 即: fooMap.get("keyName") 可以工作,但 fooMap.keyNamefooMap["keyName"] 不会。

我不知道是否有特定于 Rhino 的方法可以做到这一点,或者是否有一些转换/转换实用程序可以提供帮助。 Commons BeanUtils 还不够,因为要将 Map 转换为 bean(可以通过关联数组语法访问),您必须首先创建一个具有所有命名的变元/访问器的类。我不会在运行时知道对象的结构。

Is there a way to access Java Maps and Lists as JavaScript Objects in Rhino?

I have a Map which contains only other maps and lists of primitives and Strings, I'd like to pass this to a Rhino script and do stuff to it, and return the modified object back out to Java - but since they are java.util.Map and java.util.List Objects, I can't use standard JavaScript associative array syntax.
ie: fooMap.get("keyName") will work, but fooMap.keyName and fooMap["keyName"] will not.

I don't know if there is a Rhino-specific way to do this, or if there is some conversion/cast utility that will help.
Commons BeanUtils is not sufficient, because to convert a Map to a bean (which can be accessed via associative array syntax), you must first create a class which has all of the named mutators/accessors. I won't know the structure of the object at runtime.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

飘然心甜 2024-11-15 12:42:02

看看 RingoJS。它具有方便的 Rhino 列表和地图包装器,例如 这个

Take a look at RingoJS. It has convenient wrappers for list and map for Rhino such as this one

一场春暖 2024-11-15 12:42:02

迭代器似乎是关键!

如果你想迭代地图的所有条目,你可以执行以下

JAVA

//pass  the map and map.keySet().iterator() to the javascript
Object wrappedParameterMap = Context.javaToJS(parameterMap, scope);
ScriptableObject.putProperty(scope, "parameterMap", wrappedParameterMap);
Object wrappedParameterNames = Context.javaToJS(parameterMap.keySet().iterator(), scope);
ScriptableObject.putProperty(scope, "parameterNames", wrappedParameterNames);

JAVASCRIPT

while(parameterNames.hasNext()) {
  key = parameterNames.next();
  value = parameterMap.get(key);
}

iterators seem to be the key!

if you want to iterate over all entries of a map, you could do the following

JAVA

//pass  the map and map.keySet().iterator() to the javascript
Object wrappedParameterMap = Context.javaToJS(parameterMap, scope);
ScriptableObject.putProperty(scope, "parameterMap", wrappedParameterMap);
Object wrappedParameterNames = Context.javaToJS(parameterMap.keySet().iterator(), scope);
ScriptableObject.putProperty(scope, "parameterNames", wrappedParameterNames);

JAVASCRIPT

while(parameterNames.hasNext()) {
  key = parameterNames.next();
  value = parameterMap.get(key);
}
翻身的咸鱼 2024-11-15 12:42:02

https://developer.mozilla.org/en/New_in_Rhino_1.7R3#JS .c2.a0Objects_implement_Java_collections 声明 JS 对象。数组现在可以分别转换为 MapList,但这似乎不适用于您的用例。

https://developer.mozilla.org/en/New_in_Rhino_1.7R3#JS.c2.a0Objects_implement_Java_collections claims that JS objects resp. arrays can now be cast to Map resp. List, but this does not seem like it would work for your use case.

单挑你×的.吻 2024-11-15 12:42:02

我遇到了一个可能有用的类似问题。我尝试创建本地犀牛对象并将数据复制到其中。

I had a similar problem that may be useful. I tried created native rhino objects and copied data into them.

神魇的王 2024-11-15 12:42:02

从 Rhino 1.7.12 开始,您可以创建 ES6 lambda,从而创建您自己的实用函数,如下所示:

function iterateMap(map, callback) {
    var iter = map.keySet().iterator();
    while(iter.hasNext()) {
        var key = iter.next();
        var value = map.get(key);
        callback(key, value);
    }
}

然后像这样迭代

iterateMap(map, (key, value)=>{
    //...
});

Since Rhino 1.7.12 you can create ES6 lambdas and therefore create your own utility function like this:

function iterateMap(map, callback) {
    var iter = map.keySet().iterator();
    while(iter.hasNext()) {
        var key = iter.next();
        var value = map.get(key);
        callback(key, value);
    }
}

And then iterate like this

iterateMap(map, (key, value)=>{
    //...
});
玩套路吗 2024-11-15 12:42:02

自 Rhino 1.7.14 起实现此目的的方法是启用 Context.FEATURE_ENABLE_JAVA_MAP_ACCESS 。

这需要实现一个自定义的 ContextFactory:

public class MyContextFactory extends ContextFactory {
    @Override
    protected boolean hasFeature(Context cx, int featureIndex) {
        switch (featureIndex) {
            case Context.FEATURE_ENABLE_JAVA_MAP_ACCESS:
                return true;
        }
        return super.hasFeature(cx, featureIndex);
    }
}

然后,该工厂可用于实例化启用此功能的上下文:

Map<String, String> myMap = Map.of("message", "Hello from JavaScript");

ContextFactory ctxFactory = new MyContextFactory();
try (Context ctx = ctxFactory.enterContext()) {
    Scriptable scope = ctx.initSafeStandardObjects();
    ScriptableObject.putProperty(scope, "myMap", Context.javaToJS(myMap, scope));
    
    // Now map properties are accessible via `[key]` or `.key`:
    Object result = ctx.evaluateString(scope, "myMap.message", "<sample>", 1, null);
    String message = Context.jsToJava(result, String.class);
    System.out.println(message); // prints "Hello from JavaScript"
}

The way to achieve this since Rhino 1.7.14 is to enable Context.FEATURE_ENABLE_JAVA_MAP_ACCESS.

This requires implementing a custom ContextFactory:

public class MyContextFactory extends ContextFactory {
    @Override
    protected boolean hasFeature(Context cx, int featureIndex) {
        switch (featureIndex) {
            case Context.FEATURE_ENABLE_JAVA_MAP_ACCESS:
                return true;
        }
        return super.hasFeature(cx, featureIndex);
    }
}

Then, this factory can be used to instantiate contexts that has this feature enabled:

Map<String, String> myMap = Map.of("message", "Hello from JavaScript");

ContextFactory ctxFactory = new MyContextFactory();
try (Context ctx = ctxFactory.enterContext()) {
    Scriptable scope = ctx.initSafeStandardObjects();
    ScriptableObject.putProperty(scope, "myMap", Context.javaToJS(myMap, scope));
    
    // Now map properties are accessible via `[key]` or `.key`:
    Object result = ctx.evaluateString(scope, "myMap.message", "<sample>", 1, null);
    String message = Context.jsToJava(result, String.class);
    System.out.println(message); // prints "Hello from JavaScript"
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文