問題背景:
當前在Oracle數據庫(11G之前的版本)解析json沒有可以直接使用的系統方法,網上流傳的PLSQL腳本大多也只可以解析結構較單一的json串,對於結構復雜的json串還無法解析。如此一來導致即便可以在PL/SQL中調用遠程接口,但返回結果仍需傳給前台js或java等其它代碼進行處理,不太方便。
分析思路:
1、在PL/SQL中寫json串,無需聲明json對象,只需直接拼接成格式正確的json字符串即可,因此數據庫對象間json串的傳遞完全可以用varchar2或clob來代替。
2、結構復雜的json串節點元素值基本上可以分為兩類:①仍為json串②json數組,因此我們只需對這兩種類型的json對象進行處理即可。
3、在PL/SQL中處理json數組時,由於json元素是無序且可以重復的,因此我們需要對數組成員進行索引並能夠獲取數組長度才可以對其循環處理。
4、java中有很多可以方便解析json串的開源jar包,且數據庫支持導入java類文件,因此是否可以將java代碼編譯生成的class導入數據處理json呢?
解決方案:
方法1:loadjava導入java類進行解析
1、查看當前數據庫已導入的java類文件
2、執行loadjava命令導入處理json所需jar文件,在此選擇org.json而不選擇fastjson或jackson的原因是該jar包沒有外部依賴且滿足功能的同時所需導入類文件較少。
--向數據庫導入json相關jar包 loadjava -r -f -u scott/tiger@xxx.xxx.xxx.xxx:1521/orcl json.jar --刪除指定jar #dropjava -u scott/tiger@xxx.xxx.xxx.xxx:1521/orcl json.jar
在此,我們執行導入,如下:
細節:如果導入的jar包存在外部依賴,會報如下異常,繼續導入外部依賴只會使要導入的jar包越來越多,最終還不一定可以導入成功,得不償失,如下:
3、導入json.jar成功后再次查看當前已導入的類文件如下
4、在數據庫SQL窗口執行以下腳本,創建java源碼對象
1 create or replace and compile java source named "JsonUtil" as 2 3 import org.json.JSONArray; 4 import org.json.JSONException; 5 import org.json.JSONObject; 6 import java.lang.Integer; 7 8 public class JsonUtil { 9 10 //取json串單個節點值 11 public static String getValue(String jsonStr,String nodeName){ 12 String nodeValue=""; 13 try { 14 if(jsonStr==null||!jsonStr.startsWith("{")||!jsonStr.endsWith("}")){ 15 nodeValue=""; 16 }else{ 17 JSONObject obj =new JSONObject(jsonStr); 18 nodeValue = obj.getString(nodeName); 19 } 20 } catch (JSONException e) { 21 nodeValue=""; 22 } 23 return nodeValue; 24 } 25 //取json數組長度便於循環處理 26 public static Integer getArrayLength(String jsonArrayStr){ 27 Integer length=0; 28 try { 29 if(jsonArrayStr==null||!jsonArrayStr.startsWith("[")||!jsonArrayStr.endsWith("]")){ 30 length=0; 31 }else{ 32 JSONArray jsonArr = new JSONArray(jsonArrayStr); 33 length=jsonArr.length(); 34 } 35 } catch (JSONException e) { 36 length=0; 37 } 38 return length; 39 } 40 41 //取json數組第index個元素 42 public static String getArrayValue(String jsonStr,Integer index){ 43 String nodeValue=""; 44 try { 45 if(jsonStr==null||!jsonStr.startsWith("[")||!jsonStr.endsWith("]")){ 46 nodeValue=""; 47 }else{ 48 JSONArray jsonArr = new JSONArray(jsonStr); 49 nodeValue=jsonArr.getString(index); 50 } 51 } catch (JSONException e) { 52 nodeValue=""; 53 } 54 return nodeValue; 55 } 56 }
創建成功后再次查詢可以看到對應的class文件:
5、利用步驟4創建的class創建function(或procedure),在此為了使其跟目前數據庫已存在的json處理方法區分開,我們創建一個package,如下:
1 create or replace package jsonpkg 2 as 3 function getval(jsonstr varchar2,nodename varchar2) return varchar2; 4 function getarrval(jsonArrayStr varchar2,seqNo number) return varchar2; 5 function getarrlen(jsonArrayStr varchar2) return number; 6 end jsonpkg; 7 / 8 create or replace package body jsonpkg 9 as 10 function getval(jsonstr varchar2,nodename varchar2) return varchar2 11 as language java name 'JsonUtil.getValue(java.lang.String,java.lang.String) return java.lang.String'; 12 13 function getarrval(jsonArrayStr varchar2,seqNo number) return varchar2 14 as language java name 'JsonUtil.getArrayValue(java.lang.String, java.lang.Integer) return java.lang.String'; 15 16 function getarrlen(jsonArrayStr varchar2) return number 17 as language java name 'JsonUtil.getArrayLength(java.lang.String) return java.lang.Integer'; 18 19 end jsonpkg; 20 /
創建成功后可以查看包說明和主體:
6、測試
①簡單json測試
②解析復雜json
至此,我們就可以很輕松的就取到json串中任意節點的值(如果節點值為數組則可以先計算數組長度再進行loop循環處理,或直接用getarrval方法取指定數組元素的值)。
方法2:安裝開源組件PL/JSON
下載地址: https://github.com/pljson/pljson
優點:安裝方便,解析方法較專業;缺點:新增數據庫對象較多,短期學習成本較高。文檔很詳細,在此不再贅述。
尊重他人勞動成果,轉載請注明本文鏈接:http://www.cnblogs.com/mobeiyan/p/6810243.html