• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Java用 Rhino/Nashorn 代替第三方 JSON 转换库

java 搞代码 4年前 (2022-01-05) 24次浏览 已收录 0个评论

本篇文章主要介绍了Java用 Rhino/Nashorn 代替第三方 JSON 转换库,非常具有实用价值,需要的朋友可以参考下

Java 本身就自带 JS 引擎,自从 Java 1.6 开始就支持了,愈来愈好。我对 js 比较熟悉,因此有个大胆的想法,为什么不用自带 js 引擎作 json 转换呢?这样我们可以不用引入其他第三方库。

背景知识:Java 6 提供对执行脚本语言的支持,这个支持来自于 JSR223 规范,对应的包是 javax.script。默认情况下,Java 6 只支持 JavaScript 脚本,它底层的实现是 Mozilla Rhino,它是个纯 Java 的 JavaScript 实现。

除了 OpenJDK 不自带 js 引擎外,Sun/Oracle 的都支持。所以完全可以这么来做。

我本人很早就这么做了。只是早期 1.6/1.7 的 Rhino 性能低下,但到了 1.8 性能已经不能同日而语了,――因为已经升级到 Nashorn 引擎了,一个非常快的 js 引擎实现。另外一点,之前写的代码十分累赘。尽管也重构了几次,但还是写不好。于是现欲改之,改成为一个稍“明快”的版本。请各位看官见下面代码,其作用就是将 JSON 字符串转换为 Java 的 Map 或者 List。

 import java.util.List; import java.util.Map; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; /** * json 转为 java 对象的工具类 * * @author frank * */ public class JSON { /** * 创建 js 引擎工厂,支持 java 6/7 的 rhino 和 java 8 的 nashorn * * @return js 引擎 */ public static ScriptEngine engineFatory() { return new ScriptEngineManager() .getEngineByName(System.getProperty("java.version").contains("1.8.") ? "nashorn" : "rhino"); } /** * JVM 自带的 JS 引擎 */ private final static ScriptEngine engine = engineFatory(); /** * 读取 json 里面的 map * * @param js *      JSON 字符串 * @param key *      JSON Path,可以带有 aa.bb.cc * @return Map 对象 */ @SuppressWarnings("unchecked") public static Map getMap(String js, String key) { return (Map) accessMember(js, key, Map.class); } /** * 读取 json 里面的 map * * @param js *      JSON 字符串 * @return Map 对象 */ public static Map getMap(String js) { return getMap(js, null); } /** * 转换为 map 或 list * * @param js *      JSON 字符串 * @param key *      JSON Path,可以带有 aa.bb.cc * @param clazz *      目标类型 * @return 目标对象 */ @SuppressWarnings("unchecked") public static  T accessMember(String js, String key, Class clazz) { T result = null; try { engine.eval("var obj = " + js);// rhino 不能直接返回 map,如 eval("{a:1}") // -->null,必须加变量,例如 执行 var xx = // {...}; Object obj; if (key == null) { obj = engine.eval("obj;"); } else { if (key.contains(".")) { obj = engine.eval("obj." + key + ";"); } else { obj = engine.eval("obj['" + key + "'];"); } } result = (T) obj; } catch (ScriptException e) { System.err.println("脚本eval()运算发生异常!eval 代码:" + js); e.printStackTrace(); } return result; } /** * 读取 json 里面的 list,list 里面每一个都是 map * * @param js *      JSON 字符串 * @param key *      JSON Path,可以带有 aa.bb.cc * @return 包含 Map 的列表 */ @SuppressWarnings("unchecked") public static List<Map> getList(String js, String key) { return (List<Map>) accessMember(js, key, List.class); } /** * 读取 json 里面的 list,list 里面每一个都是 map * * @param js *      JSON 字符串 * @return 包含 Map 的列表 */ public static List<Map> getList(String js) { return getList(js, null); } /** * 读取 json 里面的 list,list 里面每一个都是 String * * @param js *      JSON 字符串 * @param key *      JSON Path,可以带有 aa.bb.cc * @return 包含 String 的列表 */ @SuppressWarnings("unchecked") public static List getStringList(String js, String key) { return (List) accessMember(js, key, List.class); } /** * 读取 json 里面的 list,list 里面每一个都是 String * * @param js *      JSON 字符串 * @return 包含 String 的列表 */ public static List getStringList(String js) { return getStringList(js, null); } /** * js number 为 double 类型,在 java 里面使用不方便,将其转换为 int * * @param d *      js number * @return int 值 */ public static int double2int(Double d) { if (d > Integer.MAX_VALUE) { System.out.println(d + "数值太大,不应用这个方法转换到 int"); return 0; } else { return d.intValue(); } } } 

其实使用起来非常地方便!js 的对象本身是 map 结构,而 Rhino 原生对象 NativeObject 是 js 对象在 Java 语言里面的对应物,它已经实现了 Map 接口,所以完全可以把 NativeObject 当作 map 来使用!类型转换下即可!eval() 返回的是 object,如果可以判断 object 类型为 NativeObject,直接转化 (Map)object 就可以了――接着就是使用 get 等方法,甚至在 JSP 页面中也可以使用。

List 的也是同理。

下面是单测的代码。

 import java.util.List; import java.util.Map; import org.junit.Test; import com.ajaxjs.util.json.JSON; import static org.junit.Assert.*; public class TestJSON { @Test public void testGetMap() { Map map; map = JSON.getMap("{a:'hello', b: 'world!', c: { d: 'Nice!'}}"); System.out.println(map.get("a")); assertNotNull(map); map = JSON.getMap("{a:'hello', b: 'world!', c: { d: 'Nice!'}}", "c"); System.out.println(map.get("d")); assertNotNull(map); map = JSON.getMap("{a:'hello', b: 'world!', c: { d: 'Nice!', e: { f: 'fff'}}}", "c.e"); System.out.println(map.get("f")); assertNotNull(map); } @Test public void testGetListMap() { List<Map> list; list = JSON.getList("[{a:'hello'}, 123, true]"); System.out.println(list.get(0).get("a")); assertTrue(list.size() > 0); list = JSON.getList("[{a:<strong style="color:transparent">来源gao@daima#com搞(%代@#码@网</strong>'hello'}, {b: 'world!'}, {c: { d: 'Nice!'}}]"); System.out.println(list.get(0).get("a")); assertTrue(list.size() > 0); list = JSON.getList("{a:'hello', b: 'world!', c: [{ d: 'Nice!!!'}]}", "c"); System.out.println(list.get(0).get("d")); } @Test public void testGetListString() { List list; list = JSON.getStringList("['a', 'b', 'c']"); System.out.println(list.get(0)); assertTrue(list.size() > 0); list = JSON.getStringList("[1, 'b', 'c']"); System.out.println(list.get(1)); assertTrue(list.size() > 0); } } 

值得注意的是,虽然 JSEngine 提供了 Map 接口,但通常只能读的操作,如果对其执行 map.put(key, value) 的操作,是会引发 UnsupportOperation 的异常的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持gaodaima搞代码网

以上就是Java用 Rhino/Nashorn 代替第三方 JSON 转换库的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Java用 Rhino/Nashorn 代替第三方 JSON 转换库

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址