如何将 Java Map 转换为基本的 Javascript 对象?

发布于 2024-12-06 12:42:30 字数 388 浏览 0 评论 0原文

我开始使用 Java 6 中的动态 rhinoscript 功能,供那些更了解 Javascript 而不是 Java 的客户使用。

将 Map(关联数组、javascript obj 等)传递到 Javascript 以便脚本编写者可以使用标准 Javascript 点表示法来访问值的最佳方法是什么?

我当前正在将 java.util.Map 值传递到脚本中,但是脚本编写者必须编写“map.get('mykey')”而不是“map.mykey”。

基本上,我想做与这个问题相反的事情。

I'm starting to use the dynamic rhinoscript feature in Java 6 for use by customers who are more likely to know Javascript than Java.

What is the best way to pass a Map (associative array, javascript obj, whatever) into Javascript so the script-writers can use the standard Javascript dot notation for accessing values?

I'm currently passing a java.util.Map of values into the script, however then the script writer has to write "map.get('mykey')" instead of "map.mykey".

Basically, I want to do the opposite of this question.

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

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

发布评论

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

评论(4

人│生佛魔见 2024-12-13 12:42:30

我采用了 Java NativeObject 方法,这就是我所做的......

// build a Map
Map<String, String> map = new HashMap<String, String>();
map.put("bye", "now");

// Convert it to a NativeObject (yes, this could have been done directly)
NativeObject nobj = new NativeObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
    nobj.defineProperty(entry.getKey(), entry.getValue(), NativeObject.READONLY);
}

// Get Engine and place native object into the context
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("javascript");
engine.put("map", nobj);

// Standard Javascript dot notation prints 'now' (as it should!)
engine.eval("println(map.bye);");

I took the Java NativeObject approach and here is what I did...

// build a Map
Map<String, String> map = new HashMap<String, String>();
map.put("bye", "now");

// Convert it to a NativeObject (yes, this could have been done directly)
NativeObject nobj = new NativeObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
    nobj.defineProperty(entry.getKey(), entry.getValue(), NativeObject.READONLY);
}

// Get Engine and place native object into the context
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("javascript");
engine.put("map", nobj);

// Standard Javascript dot notation prints 'now' (as it should!)
engine.eval("println(map.bye);");
倾城°AllureLove 2024-12-13 12:42:30

我正在使用一个实用程序类,将 Map 转换为 javascript 哈希对象:

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.mozilla.javascript.Scriptable;
public class MapScriptable implements Scriptable, Map {
    public final Map map;
    public MapScriptable(Map map) {
        this.map = map;
    }
    public void clear() {
        map.clear();
    }
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }
    public Set entrySet() {
        return map.entrySet();
    }
    public boolean equals(Object o) {
        return map.equals(o);
    }
    public Object get(Object key) {
        return map.get(key);
    }
    public int hashCode() {
        return map.hashCode();
    }
    public boolean isEmpty() {
        return map.isEmpty();
    }
    public Set keySet() {
        return map.keySet();
    }
    public Object put(Object key, Object value) {
        return map.put(key, value);
    }
    public void putAll(Map m) {
        map.putAll(m);
    }
    public Object remove(Object key) {
        return map.remove(key);
    }
    public int size() {
        return map.size();
    }
    public Collection values() {
        return map.values();
    }
    @Override
    public void delete(String name) {
        map.remove(name);
    }
    @Override
    public void delete(int index) {
        map.remove(index);
    }
    @Override
    public Object get(String name, Scriptable start) {
        return map.get(name);
    }
    @Override
    public Object get(int index, Scriptable start) {
        return map.get(index);
    }
    @Override
    public String getClassName() {
        return map.getClass().getName();
    }
    @Override
    public Object getDefaultValue(Class<?> hint) {
        return toString();
    }
    @Override
    public Object[] getIds() {
        Object[] res=new Object[map.size()];
        int i=0;
        for (Object k:map.keySet()) {
            res[i]=k;
            i++;
        }
        return res;
    }
    @Override
    public Scriptable getParentScope() {
        return null;
    }
    @Override
    public Scriptable getPrototype() {
        return null;
    }
    @Override
    public boolean has(String name, Scriptable start) {
        return map.containsKey(name);
    }
    @Override
    public boolean has(int index, Scriptable start) {
        return map.containsKey(index);
    }
    @Override
    public boolean hasInstance(Scriptable instance) {
        return false;
    }
    @Override
    public void put(String name, Scriptable start, Object value) {
        map.put(name, value);
    }
    @Override
    public void put(int index, Scriptable start, Object value) {
        map.put(index, value);
    }
    @Override
    public void setParentScope(Scriptable parent) {}
    @Override
    public void setPrototype(Scriptable prototype) {}
}

示例:

import java.util.HashMap;
import java.util.Map;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ScriptableObject;

public class MapScriptableMain {
    public static void main(String[] args) {
        Map src=new HashMap();
        src.put("foo", 2);
        src.put("bar", 3);
        MapScriptable m=new MapScriptable(src);
        Context c=Context.enter();
        ScriptableObject scope = c.initStandardObjects();
        ScriptableObject.putProperty(scope, "m", m);
        String source = "m.baz=m.foo+m.bar;";
        Object a=c.evaluateString(scope, source, "TEST", 1, null);
        System.out.println(a); // 5.0
        System.out.println(src.get("baz")); // 5.0;
    }
}

I am using an utility class that convert Map into javascript hash object:

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.mozilla.javascript.Scriptable;
public class MapScriptable implements Scriptable, Map {
    public final Map map;
    public MapScriptable(Map map) {
        this.map = map;
    }
    public void clear() {
        map.clear();
    }
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }
    public Set entrySet() {
        return map.entrySet();
    }
    public boolean equals(Object o) {
        return map.equals(o);
    }
    public Object get(Object key) {
        return map.get(key);
    }
    public int hashCode() {
        return map.hashCode();
    }
    public boolean isEmpty() {
        return map.isEmpty();
    }
    public Set keySet() {
        return map.keySet();
    }
    public Object put(Object key, Object value) {
        return map.put(key, value);
    }
    public void putAll(Map m) {
        map.putAll(m);
    }
    public Object remove(Object key) {
        return map.remove(key);
    }
    public int size() {
        return map.size();
    }
    public Collection values() {
        return map.values();
    }
    @Override
    public void delete(String name) {
        map.remove(name);
    }
    @Override
    public void delete(int index) {
        map.remove(index);
    }
    @Override
    public Object get(String name, Scriptable start) {
        return map.get(name);
    }
    @Override
    public Object get(int index, Scriptable start) {
        return map.get(index);
    }
    @Override
    public String getClassName() {
        return map.getClass().getName();
    }
    @Override
    public Object getDefaultValue(Class<?> hint) {
        return toString();
    }
    @Override
    public Object[] getIds() {
        Object[] res=new Object[map.size()];
        int i=0;
        for (Object k:map.keySet()) {
            res[i]=k;
            i++;
        }
        return res;
    }
    @Override
    public Scriptable getParentScope() {
        return null;
    }
    @Override
    public Scriptable getPrototype() {
        return null;
    }
    @Override
    public boolean has(String name, Scriptable start) {
        return map.containsKey(name);
    }
    @Override
    public boolean has(int index, Scriptable start) {
        return map.containsKey(index);
    }
    @Override
    public boolean hasInstance(Scriptable instance) {
        return false;
    }
    @Override
    public void put(String name, Scriptable start, Object value) {
        map.put(name, value);
    }
    @Override
    public void put(int index, Scriptable start, Object value) {
        map.put(index, value);
    }
    @Override
    public void setParentScope(Scriptable parent) {}
    @Override
    public void setPrototype(Scriptable prototype) {}
}

Sample:

import java.util.HashMap;
import java.util.Map;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ScriptableObject;

public class MapScriptableMain {
    public static void main(String[] args) {
        Map src=new HashMap();
        src.put("foo", 2);
        src.put("bar", 3);
        MapScriptable m=new MapScriptable(src);
        Context c=Context.enter();
        ScriptableObject scope = c.initStandardObjects();
        ScriptableObject.putProperty(scope, "m", m);
        String source = "m.baz=m.foo+m.bar;";
        Object a=c.evaluateString(scope, source, "TEST", 1, null);
        System.out.println(a); // 5.0
        System.out.println(src.get("baz")); // 5.0;
    }
}
酸甜透明夹心 2024-12-13 12:42:30

在弄清楚 SimpleScriptContext 将仅采用 Map 对象并从而强制您在 JavaScript 中使用 Java 方法之后,这就是我所做的。

Map<String, String> myMap = new HashMap<String, String>();
myMap.put("test", "hello world!");

ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Object eval = engine.eval("var map = " + new Gson().toJson(myMap) + ";\n" 
    + "println(map.test);");

哪个打印出来了

hello world!

After figuring out that the SimpleScriptContext will only take the Map object and thus force you to use the Java methods in your JavaScript, here's what I did.

Map<String, String> myMap = new HashMap<String, String>();
myMap.put("test", "hello world!");

ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Object eval = engine.eval("var map = " + new Gson().toJson(myMap) + ";\n" 
    + "println(map.test);");

Which printed out

hello world!
赠我空喜 2024-12-13 12:42:30

您只需将对象编码为 JSON,手动或使用 杰克逊gson。正如您所说,这与该问题完全相反,并且该问题的作者对 JSON 表示法不满意:)

您需要发送到浏览器的内容基本上是这样的:

var someObject = { "key1": "value1", "key2": "value2", ... }

然后 javascript 开发人员可以简单地访问: <代码>someObject.key2。

You just need to encode your object as JSON, either manually, or using a library like Jackson or gson. As you said, it's the exact oposite of that question and the author of that question is not happy with the JSON notation :)

What you need to send to the browser is basically something like this:

var someObject = { "key1": "value1", "key2": "value2", ... }

And then the javascript developer can simply access: someObject.key2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文