Oracle解析復(fù)雜json的方法實(shí)例詳解
問(wèn)題背景:
當(dāng)前在Oracle數(shù)據(jù)庫(kù)(11G之前的版本)解析json沒(méi)有可以直接使用的系統(tǒng)方法,網(wǎng)上流傳的PLSQL腳本大多也只可以解析結(jié)構(gòu)較單一的json串,對(duì)于結(jié)構(gòu)復(fù)雜的json串還無(wú)法解析。如此一來(lái)導(dǎo)致即便可以在PL/SQL中調(diào)用遠(yuǎn)程接口,但返回結(jié)果仍需傳給前臺(tái)js或java等其它代碼進(jìn)行處理,不太方便。
分析思路:
1、在PL/SQL中寫(xiě)json串,無(wú)需聲明json對(duì)象,只需直接拼接成格式正確的json字符串即可,因此數(shù)據(jù)庫(kù)對(duì)象間json串的傳遞完全可以用varchar2或clob來(lái)代替。
2、結(jié)構(gòu)復(fù)雜的json串節(jié)點(diǎn)元素值基本上可以分為兩類(lèi):①仍為json串②json數(shù)組,因此我們只需對(duì)這兩種類(lèi)型的json對(duì)象進(jìn)行處理即可。

3、在PL/SQL中處理json數(shù)組時(shí),由于json元素是無(wú)序且可以重復(fù)的,因此我們需要對(duì)數(shù)組成員進(jìn)行索引并能夠獲取數(shù)組長(zhǎng)度才可以對(duì)其循環(huán)處理。
4、java中有很多可以方便解析json串的開(kāi)源jar包,且數(shù)據(jù)庫(kù)支持導(dǎo)入java類(lèi)文件,因此是否可以將java代碼編譯生成的class導(dǎo)入數(shù)據(jù)處理json呢?
解決方案:
方法1:loadjava導(dǎo)入java類(lèi)進(jìn)行解析
1、查看當(dāng)前數(shù)據(jù)庫(kù)已導(dǎo)入的java類(lèi)文件
2、執(zhí)行l(wèi)oadjava命令導(dǎo)入處理json所需jar文件,在此選擇org.json而不選擇fastjson或jackson的原因是該jar包沒(méi)有外部依賴(lài)且滿(mǎn)足功能的同時(shí)所需導(dǎo)入類(lèi)文件較少。
--向數(shù)據(jù)庫(kù)導(dǎo)入json相關(guān)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
在此,我們執(zhí)行導(dǎo)入,如下:

細(xì)節(jié):如果導(dǎo)入的jar包存在外部依賴(lài),會(huì)報(bào)如下異常,繼續(xù)導(dǎo)入外部依賴(lài)只會(huì)使要導(dǎo)入的jar包越來(lái)越多,最終還不一定可以導(dǎo)入成功,得不償失,如下:

3、導(dǎo)入json.jar成功后再次查看當(dāng)前已導(dǎo)入的類(lèi)文件如下

4、在數(shù)據(jù)庫(kù)SQL窗口執(zhí)行以下腳本,創(chuàng)建java源碼對(duì)象
create or replace and compile java source named "JsonUtil" as
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.Integer;
public class JsonUtil {
//取json串單個(gè)節(jié)點(diǎn)值
public static String getValue(String jsonStr,String nodeName){
String nodeValue="";
try {
if(jsonStr==null||!jsonStr.startsWith("{")||!jsonStr.endsWith("}")){
nodeValue="";
}else{
JSONObject obj =new JSONObject(jsonStr);
nodeValue = obj.getString(nodeName);
}
} catch (JSONException e) {
nodeValue="";
}
return nodeValue;
}
//取json數(shù)組長(zhǎng)度便于循環(huán)處理
public static Integer getArrayLength(String jsonArrayStr){
Integer length=0;
try {
if(jsonArrayStr==null||!jsonArrayStr.startsWith("[")||!jsonArrayStr.endsWith("]")){
length=0;
}else{
JSONArray jsonArr = new JSONArray(jsonArrayStr);
length=jsonArr.length();
}
} catch (JSONException e) {
length=0;
}
return length;
}
//取json數(shù)組第index個(gè)元素
public static String getArrayValue(String jsonStr,Integer index){
String nodeValue="";
try {
if(jsonStr==null||!jsonStr.startsWith("[")||!jsonStr.endsWith("]")){
nodeValue="";
}else{
JSONArray jsonArr = new JSONArray(jsonStr);
nodeValue=jsonArr.getString(index);
}
} catch (JSONException e) {
nodeValue="";
}
return nodeValue;
}
}
創(chuàng)建成功后再次查詢(xún)可以看到對(duì)應(yīng)的class文件:

5、利用步驟4創(chuàng)建的class創(chuàng)建function(或procedure),在此為了使其跟目前數(shù)據(jù)庫(kù)已存在的json處理方法區(qū)分開(kāi),我們創(chuàng)建一個(gè)package,如下:
create or replace package jsonpkg as function getval(jsonstr varchar2,nodename varchar2) return varchar2; function getarrval(jsonArrayStr varchar2,seqNo number) return varchar2; function getarrlen(jsonArrayStr varchar2) return number; end jsonpkg; / create or replace package body jsonpkg as function getval(jsonstr varchar2,nodename varchar2) return varchar2 as language java name 'JsonUtil.getValue(java.lang.String,java.lang.String) return java.lang.String'; function getarrval(jsonArrayStr varchar2,seqNo number) return varchar2 as language java name 'JsonUtil.getArrayValue(java.lang.String, java.lang.Integer) return java.lang.String'; function getarrlen(jsonArrayStr varchar2) return number as language java name 'JsonUtil.getArrayLength(java.lang.String) return java.lang.Integer'; end jsonpkg; /
創(chuàng)建成功后可以查看包說(shuō)明和主體:


6、測(cè)試
①簡(jiǎn)單json測(cè)試



②解析復(fù)雜json

至此,我們就可以很輕松的就取到j(luò)son串中任意節(jié)點(diǎn)的值(如果節(jié)點(diǎn)值為數(shù)組則可以先計(jì)算數(shù)組長(zhǎng)度再進(jìn)行l(wèi)oop循環(huán)處理,或直接用getarrval方法取指定數(shù)組元素的值)。
方法2:安裝開(kāi)源組件PL/JSON
下載地址: https://github.com/pljson/pljson

優(yōu)點(diǎn):安裝方便,解析方法較專(zhuān)業(yè);缺點(diǎn):新增數(shù)據(jù)庫(kù)對(duì)象較多,短期學(xué)習(xí)成本較高。文檔很詳細(xì),在此不再贅述。如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Oracle 創(chuàng)建監(jiān)控賬戶(hù) 提高工作效率
有很多Oracle服務(wù)器,需要天天查看TableSpace,比較麻煩了。2009-10-10
oracle遠(yuǎn)程連接服務(wù)器數(shù)據(jù)庫(kù)圖文教程
這篇文章主要為大家詳細(xì)介紹了oracle遠(yuǎn)程連接服務(wù)器數(shù)據(jù)庫(kù)的圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
教你設(shè)計(jì)大型Oracle數(shù)據(jù)庫(kù)
表及索引的存儲(chǔ)容量估算是根據(jù)其記錄長(zhǎng)度及估算的最大記錄數(shù)確定的。在容量計(jì)算中考慮了數(shù)據(jù)塊的頭開(kāi)銷(xiāo)及記錄和字段的頭開(kāi)銷(xiāo)等等。表及索引的initial和next存儲(chǔ)參數(shù)一般設(shè)為相等,pctincrease設(shè)為0。2009-06-06
Oracle除去數(shù)據(jù)中的換行符以免讀取出現(xiàn)問(wèn)題
將整條數(shù)據(jù)取出,并用特殊符號(hào)分割,如果數(shù)據(jù)出現(xiàn)換行的情況,那么讀取時(shí)就有問(wèn)題,這時(shí)就可以采用下面的方法來(lái)去除2014-07-07
Oracle中時(shí)間日期轉(zhuǎn)化函數(shù)to_date和to_char的具體使用
時(shí)間日期轉(zhuǎn)化函數(shù)在工作中經(jīng)常可以使用的到,本文主要介紹了Oracle中時(shí)間日期轉(zhuǎn)化函數(shù)to_date和to_char的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-05-05
ORACLE常見(jiàn)錯(cuò)誤代碼的分析與解決(一)
ORACLE常見(jiàn)錯(cuò)誤代碼的分析與解決(一)...2007-03-03
MS Server和Oracle中對(duì)NULL處理的一些細(xì)節(jié)差異
SQL Server和Oracle中對(duì)插入數(shù)據(jù)值包含空的處理有所差異,在SQL Server中,我們可以把表字段設(shè)計(jì)為非空,但我們?nèi)匀豢梢酝ㄟ^(guò)下面語(yǔ)句執(zhí)行插入操作2009-06-06
Oracle數(shù)據(jù)庫(kù)中如何給表賦予權(quán)限
賦權(quán)是指將特定的權(quán)限授予用戶(hù)或用戶(hù)組,以便他們可以執(zhí)行特定的操作,如查詢(xún)、插入、更新和刪除數(shù)據(jù),創(chuàng)建和修改表結(jié)構(gòu),以及執(zhí)行其他管理任務(wù),這篇文章主要給大家介紹了關(guān)于Oracle數(shù)據(jù)庫(kù)中如何給表賦予權(quán)限的相關(guān)資料,需要的朋友可以參考下2024-01-01
Windows Sever 2012下Oracle 12c安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Windows Sever 2012下Oracle 12c安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04

