java - 如何从 JSObject 转换为 Map(反之亦然)或列出 JSObject 成员

标签 java javascript json applet jsobject

Javascript 中,我有以下代码:

var r=applet.foo({var0:99,var1:'foo',var2:applet});

在我的 Java 小程序中,我有以下内容:

public JSObject foo(JSObject args){
    System.out.println("The function is correctly invoked");
    //In fact, the following works perfectly:
    System.out.println("var1 is:"+(String)args.getMember("var1"));
    JSObject w=JSObject.getWindow(this);
    JSObject j=(JSObject)w.eval("new Object();");
    Map m=new Hashmap();

    //TODO here all the keys and values of args should be added to m

    m.put("hello","world");

    //TODO here all the keys and values of m should be added to j

    return j;
}

如何做到这一点? (待办事项)


阅读 http://docstore.mik.ua/orelly/web/jscript/ch19_06.html ,我注意到 JSObject 有一个 getSlot 方法,但如果我这样做了

args.getSlot(0)

我只有一个异常(exception):

netscape.javascript.JSException: No such slot 0 on JavaScript object
...

最佳答案

不幸的是,Errandir 的解决方案只有在您知道可用于访问您想要获取其属性名称的对象的全局变量名称时才有效。您需要知道此名称才能将 keys 方法添加到对象,并使用 JSObjectcall 调用它。方法稍后。当然,如果有,您可以将对象的全局名称传递给 Java。这个解决方案看起来不太好,尤其是当您不能在全局上下文中引用您的对象时。

作为替代方案,我建议使用 JSObjectevalthis注释中的方法假设它将完成所有工作。确实如此。但令人失望的是,它只能在 Mozilla Firefox 和 Opera 中按预期工作。在 Internet Explorer 9 和 Google Chrome 中(在 Windows 7 和 Ubuntu 12.04 LTS 下测试)thiseval 方法总是引用 applet 的文档窗口忽略哪个 JavaScript 对象 JSObject 实例实际表示。我不知道这是一个错误还是简单的 LiveConnect这些浏览器的支持很差。

好消息是 JSObjectcall 方法在适当的上下文中执行指定的函数。牢记这一点,我终于找到了一个解决方案,即如何检索 JavaScript 对象属性的名称列表。这个想法是使用 eval 方法在全局上下文中定义一个临时函数。该函数必须接收一个我们想要获取其属性的 JavaScript 对象,并将这些属性的名称作为数组返回。之后,我们可以通过 JSObjectcall 方法调用临时函数,传递有关 JavaScript 对象的 Java 表示(下面我的方法中的 jsObjectargs 在问题中听起来)。最后,可以删除临时功能。

public static ArrayList<String> getJsObjectPropertiesNames(Applet applet, JSObject jsObject) {

    if (applet == null || jsObject == null)
        return null;

    // Retrieving global context - a JSObject representing a window applet belongs to
    JSObject globalContext;
    try {

        globalContext = JSObject.getWindow(applet);
    }
    catch (JSException ex) {

        return null;
    }

    // Checking whether passed object is not an array
    try {

        jsObject.getSlot(0);
        return null;
    }
    catch (JSException e) {

    }

    String keysFunctionName = String.format("_getKeys%d", Calendar.getInstance().getTimeInMillis());
    jsObject.eval("window['" + keysFunctionName + "'] = function(jsObject) { return Object.keys(jsObject) }");
    JSObject propertiesNamesJsObject = (JSObject)globalContext.call(keysFunctionName, new Object[] { jsObject });
    jsObject.eval("delete(window['" + keysFunctionName + "'])");

    ArrayList<String> propertiesNames = new ArrayList<>();
    try {

        int slotIndex = 0;
        while (true) {

            Object propertyName = propertiesNamesJsObject.getSlot(slotIndex);
            if (propertyName instanceof String)
                propertiesNames.add((String)propertyName);
            slotIndex++;
        }
    }
    catch (JSException e) {

    }

    return propertiesNames;
}

关于java - 如何从 JSObject 转换为 Map(反之亦然)或列出 JSObject 成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11350967/

相关文章:

JSON 因 UTF-8 起始字节 0xa0 无效而被拒绝,但编码似乎有效

java - 如何使用 Spring Boot 检测并禁止 IP 地址发出过多请求?

java - 在两个线程之间共享扫描仪

java - 将 XML 配置直接嵌入到 Spring 应用程序上下文中

java - 通过代理 ID 或业务 ID 获取资源的 REST 方法

javascript - 按属性 nodeValue 对 Nodelist 进行排序

javascript - 处理表单的两个函数

javascript - mp3 下载 Ionic 框架 |安卓 | HTML5

python - 在mysql数据库的单个单元格中插入python字典

php - 如何使用Volley通过JSON从mysql获取多行数据