如何将Java映射转换为基本Javascript对象?
我开始在Java6中使用DynamicRhinoscript特性,以供更可能了解Javascript而不是Java的客户使用 将映射(关联数组、javascript obj等)传递到javascript中以便脚本编写者可以使用标准javascript点符号访问值的最佳方法是什么 我目前正在将值的java.util.Map传递到脚本中,但是脚本编写器必须编写“Map.get('mykey')”而不是“Map.mykey”如何将Java映射转换为基本Javascript对象?,java,javascript,rhino,Java,Javascript,Rhino,我开始在Java6中使用DynamicRhinoscript特性,以供更可能了解Javascript而不是Java的客户使用 将映射(关联数组、javascript obj等)传递到javascript中以便脚本编写者可以使用标准javascript点符号访问值的最佳方法是什么 我目前正在将值的java.util.Map传递到脚本中,但是脚本编写器必须编写“Map.get('mykey')”而不是“Map.mykey” 基本上,我想做与之相反的事情,你只需要将你的对象编码为,或者手动编码,或者使
基本上,我想做与之相反的事情,你只需要将你的对象编码为,或者手动编码,或者使用像或这样的库。正如您所说,这正是问题的关键所在,而问题的作者对JSON符号不满意:) 您需要发送到浏览器的内容基本上如下所示:
var someObject = { "key1": "value1", "key2": "value2", ... }
然后javascript开发人员可以简单地访问:
someObject.key2
我采用了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);");
//构建一个映射
Map Map=newhashmap();
地图。放(“再见”,“现在”);
//将其转换为NativeObject(是的,这可以直接完成)
NativeObject nobj=新的NativeObject();
对于(Map.Entry:Map.entrySet()){
nobj.defineProperty(entry.getKey()、entry.getValue()、NativeObject.READONLY);
}
//获取引擎并将本机对象放置到上下文中
ScriptEngineManager工厂=新ScriptEngineManager();
ScriptEngine=factory.getEngineByName(“javascript”);
引擎放置(“地图”,nobj);
//标准Javascript点符号打印“现在”(应该如此!)
engine.eval(“println(map.bye);”;
我使用一个实用程序类将映射转换为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) {}
}
在了解到
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);");
谢谢你的快速回复!这在向浏览器发送JSON时效果很好,但在服务器上效果不太好。下面是我的示例:`ScriptEngineManager工厂=new ScriptEngineManager();ScriptEngine=factory.getEngineByName(“javascript”);engine.put(“obj”,“key1\”:“value1\”,“key2\”:“value2\”);//这将返回“string”而不是“obj”。我不想让脚本编写器评估字符串,尽管我可能不得不这样做。发动机评估(“类型(obj)”;“我也是这样做的,但使用了杰克逊。我现在有点担心性能,因为脚本总是在变化。理论上,可以将Jackson的对象映射功能与
NativeObject
(@JonCarlson)支持结合使用,以缓解性能问题。另一个选项是编写一个递归遍历哈希映射的通用javascript。这似乎不起作用。它写的是“未定义”。我仍然需要使用get方法访问属性:map.get('bye')。另请参见
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!