如何将 Java Map 转换为基本的 Javascript 对象?
Posted
技术标签:
【中文标题】如何将 Java Map 转换为基本的 Javascript 对象?【英文标题】:How to convert Java Map to a basic Javascript object? 【发布时间】:2011-11-23 01:55:43 【问题描述】:我开始使用 Java 6 中的动态 rhinoscript 功能,供更可能了解 javascript 而非 Java 的客户使用。
将 Map(关联数组、javascript obj 等)传递到 Javascript 以便脚本编写者可以使用标准 Javascript 点符号来访问值的最佳方法是什么?
我目前正在将值的 java.util.Map 传递到脚本中,但是脚本编写者必须编写“map.get('mykey')”而不是“map.mykey”。
基本上,我想做与this question.相反的事情
【问题讨论】:
【参考方案1】:我采用了 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);");
【讨论】:
这似乎不起作用。它写“未定义”。我仍然需要使用 get 方法访问该属性:map.get('bye')。 另见***.com/questions/37357531/…【参考方案2】:我正在使用将 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;
【讨论】:
【参考方案3】:在弄清楚 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!
【讨论】:
我也是这样做的,但使用的是杰克逊。我现在有点担心性能,因为脚本总是在变化。理论上,可以使用 Jackson 的对象映射功能与NativeObject
(@JonCarlson) 支持相结合来缓解性能问题。另一种选择是编写一个递归遍历 hashmap 的通用 javascript。【参考方案4】:
您只需将对象编码为JSON,可以手动编码,也可以使用Jackson 或gson 等库。正如您所说,这与该问题完全相反,并且该问题的作者对 JSON 表示法不满意 :)
您需要发送到浏览器的内容基本上是这样的:
var someObject = "key1": "value1", "key2": "value2", ...
然后 javascript 开发人员可以简单地访问:someObject.key2
。
【讨论】:
感谢您的快速回复!将 JSON 发送到浏览器时效果很好,但在服务器上效果不佳。这是我的示例:` ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine 引擎 = factory.getEngineByName("javascript"); engine.put("obj", " \"key1\": \"value1\", \"key2\": \"value2\""); // 这将返回“字符串”而不是“obj”。我不想让脚本编写者评估字符串,尽管我可能不得不这样做。 engine.eval("typeof(obj);"); '以上是关于如何将 Java Map 转换为基本的 Javascript 对象?的主要内容,如果未能解决你的问题,请参考以下文章
java如何将json的数据转换为map或者list类型的?
如何将 XML 转换为 java.util.Map,反之亦然?
如何通过 scala.Float 到 java.Float k/v 转换将 Scala Map 转换为 Java Map