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

时间:2012-07-05 19:10:49

标签: 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)

我只有一个例外:

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

3 个答案:

答案 0 :(得分:3)

不幸的是,只有当您知道可用于访问要获取属性名称的对象的全局变量名称时,Errandir的解决方案才有效。您需要知道此名称才能将keys方法添加到对象,然后使用JSObject的{​​{3}}方法调用它。当然,如果有的话,可以将对象的全局名称传递给Java。这个解决方案看起来不太好,特别是当你无法在全局环境中引用你的对象时。

作为替代方案,我建议在评论中使用this JSObject的{​​{3}}方法,假设它将完成所有工作。确实如此。但令人失望的是,它只能在Mozilla Firefox和Opera中运行。在Internet Explorer 9和Google Chrome中(在Windows 7和Ubuntu 12.04 LTS下测试)this方法的eval始终引用applet的文档窗口,忽略哪个JavaScript对象JSObject实例实际代表。我不知道这是一个错误还是只是call在这些浏览器中支持得非常差。

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

args

答案 1 :(得分:1)

作为解决方案,您可以将方法keys定义为建议的here(您可以使用JSObject.eval(...)在您的java代码中执行此操作)。然后你可以得到像这样的键:

JSObject keys = (JSObject)args.call("keys", Collections.EMPTY_LIST);
keys.getSlot(0);

答案 2 :(得分:-1)

Here below I print a String, please modify it to get whatever you need.

public final static String getKeys = "{var keys = [];for (var key in this) {keys.push(key);} keys;}";

private static String printProperties(final Object o,
                                      final boolean printType,
                                      final int level,
                                      final String tab) {
    final StringBuilder sb = new StringBuilder(100);
    if (printType) {
        sb.append("(");
        sb.append(o.getClass().getSimpleName());
        sb.append(") ");
    }
    if (o instanceof JSObject) {
        sb.append("{\n");
        final JSObject js = (JSObject) o;
        final JSObject keys = (JSObject) js.eval(getKeys);
        boolean needComma = false;
        for (int i = 0;; i++) {
            final String key = (String) keys.getSlot(i);
            if ((key != null) && !(key.equals("undefined"))) {
                final Object val = js.getMember(key);
                if (!needComma) {
                    needComma = true;
                } else {
                    sb.append(",\n");
                }
                sb.append(multitab(tab, level));
                sb.append(key);
                sb.append(":");
                sb.append(printProperties(val, printType, level + 1, tab));
            } else {
                break;
            }
        }
        sb.append("\n");
        sb.append(multitab(tab, level - 1));
        sb.append("}");
    } else {
        sb.append(o);
    }
    return sb.toString();
}

private final static String tab = "  ";

private static String multitab(final String tab,
                               int i) {
    final StringBuilder sb = new StringBuilder();
    while (i-- > 0) {
        sb.append(tab);
    }
    return sb.toString();
}