国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

用 Rhino/Nashorn 代替第三方 JSON 轉換庫(第三版)

2019-11-08 02:36:54
字體:
來源:轉載
供稿:網友

無須其他第三方包,只是依賴于 java 自帶的 JVM 自帶的 Rhino/Nashorn 引擎提供 js/json 的服務。主要的兩個類是 JsEngineWrapper、JsonHelper,它們的繼承關系是 JsEngineWrapper 派生了 JsonHelper。

源碼:http://git.oschina.net/sp42/Ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/js?dir=1&filepath=ajaxjs-base%2Fsrc%2Fcom%2Fajaxjs%2Fjs

JsEngineWrapper

JsEngineWrapper 對默認的 ScriptEngine 進行封裝,提供下列方法:

提供兼容 rhino/nashron 的 js 引擎提供 加載 js 文件的 load(*.js) 方法。重載 load(class, *.js) 方法可以加載指定類位置的 js 文件;封裝 js 代碼的方法 eval 方法(自動捕獲 ScriptException 異常),并可以傳入 Class 參數(shù)轉換 js 所返回的類型為你期望的目標類型;封裝 call/put/get 等方法,詳細見例子的應用,都是基于原 ScriptEngine 的簡單封裝。

兼容 rhino/nashron

創(chuàng)建 js 引擎工廠,支持 java 6/7 的 rhino 和 java 8 的 nashorn,源碼如下:

public static ScriptEngine engineFactory() { return new ScriptEngineManager().getEngineByName(System.get可想而知,ScriptEngine 是消耗資源比較大的對象,一般建議單例使用。

加載 js 文件

JsEngineWrapper engine = new JsEngineWrapper();// 加載 js 文件。這里的 js 文件不是在前端的,而是在后端的哦Object obj;engine.load(TestJSEngineWrapper.class.getResource("test.js").getFile().toString());obj = engine.eval("foo");assertNotNull(obj);engine.load(TestJSEngineWrapper.class, "test.js");obj = engine.eval("foo");assertNotNull(obj);

對 js 引擎執(zhí)行 js 語句

js 語句是任意合法 js 語句,可以是一大串 js 代碼、變量名或表達式。一般情況下原生 eval() 返回 Object,不過我們可以強類型轉換之。注意 js 的 number 為 java 的 double。直接使用 double 不太好使,將其轉換為 int。

engine.eval("var foo ='Hello World!';");assertEquals(engine.eval("foo"), "Hello World!");assertEquals(engine.eval("foo = 'Nice day!';"), "Nice day!");assertEquals(engine.eval("foo", String.class), "Nice day!");engine.eval("bar = 111;");assertEquals(new Double(111), engine.eval("bar;", Double.class));// js Number 于 Java 為 Doubleengine.eval("bar = 222;");assertEquals(222, JsEngineWrapper.double2int(engine.eval("bar;", Double.class)));engine.eval("bar = false;");assertEquals(engine.eval("bar;", Boolean.class), false);

封裝 call/put/get 等方法

// put 賦值engine.put("a", 6);Object obj = engine.eval("a");assertNotNull(obj);assertEquals(obj, 6);// get 獲取 js hash 結構成員engine.eval("a = {b:{c:{d:1}}};");assertNotNull(engine.get("a"));assertNotNull(engine.get("a", "b", "c", "d"));// call 調用 js 函數(shù)engine.eval("function max_num(a, b){return (a > b) ? a : b;}");Object obj = engine.call("max_num", Object.class, null, 6, 4);assertEquals(6, obj);

JsonHelper

json 轉為 java 對象的工具類,反之亦提供 java 轉換為 js 的方法。該類繼承自 JsEngineWrapper。

js 引擎的 eval() 不支持直接返回任何值,如 eval(“{a:1}”)–>null,必須加變量,例如 執(zhí)行 eval(“ar xx = {…};”) 方可,故我們有 accessJsonMember 方法:

/** * js 引擎 不能直接返回 map,如 eval("{a:1}")-->null,必須加變量,例如 執(zhí)行 var xx = {...}; * * @param key * js 命名空間 JSON Path,可以帶有 . 分隔符的,如 aa.bb.cc * @param clazz * 目標類型 * @return 目標對象 */public <T> T accessJsonMember(String key, Class<T> clazz) { T result = null; String jsCode = "var obj = " + getJsonString(); eval(jsCode); if (key == null) { // 直接返回變量 jsCode = "obj;"; result = eval(jsCode, clazz); } else { jsCode = "obj." + key + ";"; result = eval(jsCode, clazz); } return result;}

String/Number/Boolean 類型需要開發(fā)者自己傳參數(shù)調用,而較復雜的 List/Map 則提供了獲取方法,用法如下:

JsonHelper engine = new JsonHelper();// accessJsonMember() 實質對 eval() 的封裝engine.setJsonString("{/"foo/" : /"88888/", /"bar/": {a:'hello', b: 'world!', c: { d: 'Nice!'}}}");Object obj;obj = engine.accessJsonMember(null, null);assertEquals(obj, null); // 永遠返回 nullobj = engine.accessJsonMember(null, Object.class);assertNotNull(obj);assertEquals(engine.accessJsonMember("foo", String.class), "88888");assertEquals(engine.accessJsonMember("bar.a", String.class), "hello");assertEquals(engine.accessJsonMember("bar.c.d", String.class), "Nice!");// 返回 java 的 mapMap<String, Object> map;engine.setJsonString("{/"foo/" : /"88888/", /"bar/":99999}");map = engine.getMap(null);assertEquals(map.get("bar"), 99999);engine.setJsonString("{a:'hello', b: 'world!', c: { d: 'Nice!', e: { f: 'fff'}}}");map = engine.getMap("c.e"); // 點 . 訪問符assertEquals(map.get("f"), "fff");// 返回 java 的 List<String>List<String> list;engine.setJsonString("['a', 'b', 'c']");list = engine.getStringList(null);assertTrue(list.size() > 0);assertEquals(list.get(0), "a");engine.setJsonString("{a:[1, 'b', 'c']}");list = engine.getStringList("a");assertTrue(list.size() > 0);assertEquals(list.get(1), "b");// 返回 java 的 List<Map>List<Map<String, Object>> list;engine.setJsonString("[{/"foo/" : /"88888/"}, {/"bar/" : /"99999/"}]");list = engine.getList(null);assertEquals(list.size(), 2);assertEquals(list.get(0).get("foo"), "88888");assertEquals(list.get(1).get("bar"), "99999");

既然有 js–>java 的方法那么亦有 java–>json 的方法:stringify(key)、stringifyObj(obj)。

engine.eval("var foo = {a:'hello', b: 'world!', c: [{ d: 'Nice!!!'}]};");assertEquals(engine.stringify("foo"), "{/"a/":/"hello/",/"b/":/"world!/",/"c/":[{/"d/":/"Nice!!!/"}]}");assertEquals(engine.stringifyObj(engine.eval("foo;")), "{/"a/":/"hello/",/"b/":/"world!/",/"c/":[{/"d/":/"Nice!!!/"}]}");Map<String, Object> map = new HashMap<>();map.put("foo", "11");map.put("bar", 2222);map.put("bar2", null);map.put("bar3", true);String jsonStr = JsonHelper.stringifyMap(map);assertEquals(jsonStr, "{/"foo/":/"11/",/"bar3/":true,/"bar/":2222,/"bar2/":null}");

還有一些靜態(tài)的方法也是能做到 stringify 之目的,時間關系這里就不展開了。

Bean2Json 是通過 js 的反射把 bean 轉換為 json 的。當然 java 也可以寫 反射不過相當?shù)穆闊┧杂?js 偷懶了……

TODO :JDK 8 下的測試。

這個思路我很早就有,中間也寫過幾個版本,總是不太令自己滿意,所以改來改去(走了一些彎路其實思路還是很簡單的)。以后不打算折騰了(當然還是歡迎您給意見我)。參見以前的:

《用 Rhino/Nashorn 代替第三方 JSON 轉換庫》《使用 Rhino 作為 Java 的 JSON 解析/轉換包》
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 靖宇县| 阿巴嘎旗| 乌兰浩特市| 汉源县| 瓦房店市| 漳浦县| 关岭| 象山县| 永宁县| 荆门市| 且末县| 上栗县| 石棉县| 闸北区| 西吉县| 高清| 奇台县| 法库县| 莱阳市| 东莞市| 桃源县| 叙永县| 乾安县| 上杭县| 澄江县| 大同县| 江门市| 平利县| 海安县| 广汉市| 合水县| 祁阳县| 赞皇县| 游戏| 菏泽市| 吉首市| 谷城县| 邵阳市| 平阴县| 新河县| 新乡县|