Contexte
J'ai besoin d'extraire quelques milliers de lignes d'Oracle et de les convertir en JSON pour pouvoir les utiliser dans SlickGrid. Actuellement, je récupère les lignes en PHP, je les convertis de ISO à UTF-8 avec iconv et je les exporte au format json avec json_encode. L'ensemble de l'opération prend environ 1 seconde du côté de la base de données et 5 secondes pour générer du JSON. C'est trop long.
La question
J'ai lu qu'Oracle 12c prend en charge JSON, mais je ne trouve pas exactement ce dont j'ai besoin.
Existe-t-il un moyen de renvoyer le résultat d'une requête SQL standard au format JSON?
supposément je voudrais émettre une requête semblable à ceci:
SELECT * from table AS JSON
et recevez un json valide semblable à ceci:
[{"col1": "value1", "col2": 2}, {"col1": "valueOfRow2", "col2": 3}]
Une chose importante est que je dois avoir échappé les séquences unicode, car j'utilise le jeu de caractères ISO-8859-2 du côté client, et que JSON doit être en UTF-8 ou avoir les séquences échappées.
Oracle 12c version 12.1.0.2 (la dernière version en date du 11.11.2014) ajoute le support JSON: https://docs.Oracle.com/database/121/NEWFT/chapter12102.htm#BGBGADCC
Il est disponible depuis le 17 octobre. https://blogs.Oracle.com/db/entry/Oracle_database_12c_release_1
Si vous ne parvenez pas à corriger/utiliser cette version, il existe un excellent package écrit par Lewis Cunningham et Jonas Krogsboell: PL/JSON * http://pljson.sourceforge.net/
C'est un excellent package (je l'ai utilisé dans de nombreuses installations de bases de données).
Les exemples fournis sont bons et couvrent la plupart des scénarios.
declare
ret json;
begin
ret := json_dyn.executeObject('select * from tab');
ret.print;
end;
/
12cR2 (disponible dans le nuage Oracle) le prend en charge de manière native.
SQL> select JSON_ARRAY(EMPLOYEE_ID, FIRST_NAME,LAST_NAME) from HR.EMPLOYEES;
JSON_ARRAY(EMPLOYEE_ID,FIRST_NAME,LAST_NAME)
--------------------------------------------------------------------------------
[100,"Steven","King"]
[101,"Neena","Kochhar"]
ou
SQL> select JSON_OBJECT('ID' is EMPLOYEE_ID , 'FirstName' is FIRST_NAME,'LastName' is LAST_NAME) from HR.EMPLOYEES;
JSON_OBJECT('ID'ISEMPLOYEE_ID,'FIRSTNAME'ISFIRST_NAME,'LASTNAME'ISLAST_NAME)
----------------------------------------------------------------------------
{"ID":100,"FirstName":"Steven","LastName":"King"}
{"ID":101,"FirstName":"Neena","LastName":"Kochhar"}
Vous pouvez utiliser xmltype pour convertir le résultat d'un SQL en XML et JSON. Voir l'article suivant pour connaître la solution qui fonctionnera pour Oracle depuis la version 9. Vous pouvez également télécharger le package itstar_xml_util:
http://stefan-armbruster.com/index.php/12-it/pl-sql/12-Oracle-xml-and-json-goodies
Un exemple simple avec la table emp:
declare
l_sql_string varchar2(2000);
l_xml xmltype;
l_json xmltype;
begin
l_sql_string := 'select a.empno, a.ename, a.job from emp a';
-- Create the XML aus SQL
l_xml := itstar_xml_util.sql2xml(l_sql_string);
-- Display the XML
dbms_output.put_line(l_xml.getclobval());
l_json := itstar_xml_util.xml2json(l_xml);
-- Display the JSON
dbms_output.put_line(l_json.getclobval());
end;
Le résultat ressemble à ceci:
{"ROWSET": [
{
"EMPNO": 7839,
"ENAME": "KING",
"JOB": "PRESIDENT"
},
{
"EMPNO": 7698,
"ENAME": "BLAKE",
"JOB": "MANAGER"
},
[...]
{
"EMPNO": 7934,
"ENAME": "MILLER",
"JOB": "CLERK"
}
]}
La prise en charge de JSON par Oracle 12c permet de stocker des objets JSON, de les interroger et de les sélectionner.
Vous avez un format de tableau et vous devez uniquement afficher vos données sous forme de fichier JSON. Ainsi, vous pouvez simplement concaténer des lignes dans {'col1': 'rowN1', 'col2': 'rowN2'} et faire le reste côté client ..__ ou vous pouvez utiliser LISTAGG pour obtenir le document entier. Exemple: http://technology.amis.nl/2011/06/14/creating-json-document-straight-from-sql-query-using-listagg-and-with-clause/
Faites attention à la limite SQL VARCHAR2 de 4000 caractères.
Vous pouvez également consulter http://database-geek.com/2009/03/25/json-in-and-out-of-Oracle-json-data-type/ Mais je ne pense pas, Ce type d'objet Oracle améliorera vos performances.
Une autre approche consiste à exporter XML en utilisant XMLType. Puis convertissez XML en JSON. XMLType prend en charge les caractères spéciaux et l'API est assez stable (vous n'aurez pas besoin de réécrire votre programme pour Oracle 14).
Pour ajouter à la réponse dans Oracle 12.2, vous pouvez créer un json comme vous le souhaitez.
SELECT JSON_ARRAY(
JSON_OBJECT (
KEY 'number' VALUE s.number,
KEY 'name' VALUE s.sname,
KEY 'location' VALUE s.loc
)
) AS student_det
FROM student s;
Essayez ceci:
:) la vie est heureuse
with data as
( select
xmlelement(e,regexp_replace('{"name":"'||colname||'"}', '[[:cntrl:]]', ''),',') col1
from tblname
)
select
rtrim(replace(replace(replace(xmlagg(col1).getclobval(),'&'||'quot;','"'),'<E>',''),'</E>',''),',')
as very_long_json
from data;