2011-09-22 70 views
13

Tôi bắt đầu sử dụng tính năng bản năng động trong Java 6 để sử dụng bởi những khách hàng có nhiều khả năng biết Javascript hơn Java.Làm thế nào để chuyển đổi Java Map sang một đối tượng Javascript cơ bản?

Cách tốt nhất để chuyển một Bản đồ (mảng kết hợp, javascript obj, bất cứ điều gì) vào Javascript để các nhà văn tập lệnh có thể sử dụng ký hiệu chấm JavaScript chuẩn để truy cập các giá trị là gì?

Tôi hiện đang chuyển một giá trị java.util.Map vào tập lệnh, tuy nhiên, người viết kịch bản phải viết "map.get ('mykey')" thay vì "map.mykey".

Về cơ bản, tôi muốn làm điều ngược lại của this question.

Trả lời

2

Bạn chỉ cần để mã hóa đối tượng của bạn như JSON, hoặc bằng tay, hoặc sử dụng một thư viện như Jackson hoặc gson. Như bạn nói, đó là đối diện chính xác của câu hỏi đó và tác giả của câu hỏi đó là không hài lòng với các ký hiệu JSON :)

Những gì bạn cần để gửi cho trình duyệt cơ bản là một cái gì đó như thế này:

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

Sau đó, nhà phát triển javascript có thể truy cập đơn giản: someObject.key2.

+0

Cảm ơn phản hồi nhanh chóng của bạn! Điều đó hoạt động tốt khi gửi JSON tới trình duyệt, nhưng nó không hoạt động tốt trên máy chủ. Dưới đây là ví dụ của tôi: '\t \t ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName ("javascript"); engine.put ("obj", "{\" key1 \ ": \" value1 \ ", \" key2 \ ": \" value2 \ "}"); // Trả về "chuỗi" thay vì "obj". Tôi không muốn làm cho // người viết kịch bản đánh giá chuỗi, mặc dù tôi có thể phải làm như vậy. engine.eval ("typeof (obj);"); ' –

+0

Bạn nên xem http://www.json.org/js.html – Sap

12

tôi mất cách tiếp cận Java NativeObject và đây là những gì tôi đã làm ...

// 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);"); 
+0

Điều này dường như không hoạt động. Nó viết "không xác định". Tôi vẫn cần truy cập thuộc tính với phương thức get: map.get ('bye'). –

+0

Xem thêm http://stackoverflow.com/questions/37357531/sun-org-mozilla-javascript-internal-nativeobject-vs-org-mozilla-javascript-nativ – Thilo

6

Tôi đang sử dụng một lớp tiện ích chuyển đổi Bản đồ thành javascript đối tượng băm:

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) {} 
} 

mẫu:

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

Sau khi tìm ra rằng SimpleScriptContext sẽ chỉ mất Map đối tượng và do đó buộc bạn phải sử dụng các phương thức Java trong JavaScript của bạn, đây là những gì tôi đã làm.

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);"); 

nào in ra

hello world! 
+1

Tôi đã làm theo cách này nhưng cũng sử dụng Jackson. Tôi hơi lo lắng về hiệu suất ngay bây giờ vì kịch bản sẽ luôn thay đổi. Về mặt lý thuyết, người ta có thể sử dụng khả năng Object Mapping của Jackson kết hợp với sự hỗ trợ 'NativeObject' (@JonCarlson) để giảm bớt những lo ngại về hiệu năng.Các tùy chọn khác là viết một javascript chung mà đệ quy đi hashmaps. –

Các vấn đề liên quan