Skip to content

Commit

Permalink
Added API to directly parse a json string containg an array
Browse files Browse the repository at this point in the history
  • Loading branch information
doberkofler committed Jun 19, 2014
1 parent 7a9bb20 commit 00d15bf
Show file tree
Hide file tree
Showing 11 changed files with 320 additions and 88 deletions.
28 changes: 18 additions & 10 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
v0.1.0:
date: 2014-04-26
changes:
- Added support for DATE types.
- Added support for JSONP.

v0.0.1:
date: 2013-09-24
changes:
- Initial release of plsql_json.
v0.2.0 - June 19, 2014

* 0.2.0 (Dieter Oberkofler)
* Now using 3 individual parse methods in json_parser allowing to parse an object, an array or any of the two. (Dieter Oberkofler)
* Added a new constructor to json_array allowing to parse a JSON string representing an array. Proposed by matthias-oe. (Dieter Oberkofler)
* Added a new constructor to json_value allowing to parse a JSON string representing an object or an array. (Dieter Oberkofler)
* Added unit tests for the new functionality. (Dieter Oberkofler)

v0.1.0 - April 26, 2014

* 0.1.0 (Dieter Oberkofler)
* Added support for DATE types.
* Added support for JSONP.

v0.0.1 - September 24, 2013

* 0.0.1 (Dieter Oberkofler)
* Initial release of plsql_json.
14 changes: 7 additions & 7 deletions install.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,15 @@
@@uninstall.sql


-- install the types
-- install the headers
@@json_keys.tps
show errors
@@json_node.tps
show errors
@@json_node.tpb
show errors
@@json_nodes.tps
show errors
@@json_value.tps
show errors
@@json_value.tpb
show errors

-- install the packages
@@json_object.tps
show errors
@@json_array.tps
Expand All @@ -41,6 +35,12 @@ show errors
show errors
@@json_debug.pks
show errors

-- install the bodies
@@json_node.tpb
show errors
@@json_value.tpb
show errors
@@json_object.tpb
show errors
@@json_array.tpb
Expand Down
11 changes: 11 additions & 0 deletions json_array.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ BEGIN
RETURN;
END json_array;

----------------------------------------------------------
-- json_array
--
CONSTRUCTOR FUNCTION json_array(SELF IN OUT NOCOPY json_array, theJSONString IN CLOB) RETURN SELF AS result
IS
BEGIN
SELF.nodes := json_parser.parse_array(theJSONString);
SELF.lastID := NULL;
RETURN;
END json_array;

----------------------------------------------------------
-- append
--
Expand Down
1 change: 1 addition & 0 deletions json_array.tps
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ TYPE json_array IS OBJECT
-- Constructors
CONSTRUCTOR FUNCTION json_array(self IN OUT NOCOPY json_array) RETURN self AS result,
CONSTRUCTOR FUNCTION json_array(SELF IN OUT NOCOPY json_array, theData IN json_value) RETURN SELF AS result,
CONSTRUCTOR FUNCTION json_array(SELF IN OUT NOCOPY json_array, theJSONString IN CLOB) RETURN SELF AS result,

-- Member setter methods
MEMBER PROCEDURE append(self IN OUT NOCOPY json_array),
Expand Down
2 changes: 1 addition & 1 deletion json_object.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ END json_object;
CONSTRUCTOR FUNCTION json_object(SELF IN OUT NOCOPY json_object, theJSONString IN CLOB) RETURN SELF AS result
IS
BEGIN
SELF.nodes := json_parser.parser(theJSONString);
SELF.nodes := json_parser.parse_object(theJSONString);
SELF.lastID := NULL;
RETURN;
END json_object;
Expand Down
140 changes: 79 additions & 61 deletions json_parser.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ FUNCTION lexer(jsrc IN OUT NOCOPY json_src) RETURN lTokens;

PROCEDURE parseMem(tokens lTokens, indx IN OUT PLS_INTEGER, mem_name VARCHAR2, mem_indx NUMBER, theParentID IN OUT BINARY_INTEGER, theLastID IN OUT BINARY_INTEGER, theNodes IN OUT NOCOPY json_nodes);

FUNCTION parse(tokens IN lTokens, firstToken IN VARCHAR2) RETURN json_nodes;

----------------------------------------------------------
-- GLOBAL MODULES
----------------------------------------------------------
Expand Down Expand Up @@ -630,7 +632,7 @@ BEGIN
RETURN;

ELSE
p_error('Expected string or }', tok);
p_error('Expected string or } but found '||tok.type_name, tok);

END CASE;

Expand Down Expand Up @@ -788,7 +790,7 @@ BEGIN
p_error('Premature exit in array', tok);
END IF;
ELSIF (tok.type_name != ']') THEN --error
p_error('Expected , or ]', tok);
p_error('Expected , or ] but found '||tok.type_name, tok);
END IF;

END LOOP;
Expand Down Expand Up @@ -929,52 +931,17 @@ BEGIN
END parseMem;

----------------------------------------------------------
-- parse_list
-- parse
--
FUNCTION parse_list(str CLOB) RETURN json_nodes
FUNCTION parse(tokens IN lTokens, firstToken IN VARCHAR2) RETURN json_nodes
IS
tokens lTokens;
--yyy obj json_list;
obj json_nodes := json_nodes();
indx PLS_INTEGER := 1;
jsrc json_src;
BEGIN
debug('parse_list');
updateDecimalPoint();
jsrc := prepareClob(str);
tokens := lexer(jsrc);
IF (tokens(indx).type_name = '[') THEN
indx := indx + 1;
--yyy obj := parseArr(tokens, indx);
ELSE
raise_application_error(-20101, 'JSON List Parser exception - no [ start found');
END IF;
IF (tokens.count != indx) THEN
p_error('] should end the JSON List object', tokens(indx));
END IF;

RETURN obj;
END parse_list;

----------------------------------------------------------
-- parser
--
FUNCTION parser(str CLOB) RETURN json_nodes
IS
tokens lTokens;
obj json_nodes := json_nodes();

indx PLS_INTEGER := 1;
jsrc json_src;
i BINARY_INTEGER;
lastToken VARCHAR2(1) := NULL;
nodes json_nodes := json_nodes();
indx PLS_INTEGER := 1;
--i BINARY_INTEGER := NULL;
aParentID BINARY_INTEGER := NULL;
aLastID BINARY_INTEGER := NULL;
BEGIN
updateDecimalPoint();
jsrc := prepareClob(str);

tokens := lexer(jsrc);

-- dump tokens
/*
dbms_output.put_line('----------LEXER-S----------');
Expand All @@ -986,42 +953,93 @@ BEGIN
dbms_output.put_line('----------LEXER-E----------');
*/

IF (tokens(indx).type_name != firstToken) THEN
raise_application_error(-20101, 'JSON Parser exception - invalid first token. Expected:'||firstToken||' bit found:'||tokens(indx).type_name);
END IF;

IF (tokens(indx).type_name = '{') THEN
lastToken := '}';
indx := indx + 1;
parseObj(tokens, indx, aParentID, aLastID, nodes);
ELSIF (tokens(indx).type_name = '[') THEN
lastToken := ']';
indx := indx + 1;
--yyy obj := parseObj(tokens, indx);
parseObj(tokens, indx, aParentID, aLastID, obj);
parseArr(tokens, indx, aParentID, aLastID, nodes);
ELSE
raise_application_error(-20101, 'JSON Parser exception - no { start found');
raise_application_error(-20101, 'JSON Parser exception - no '||firstToken||' start found');
END IF;
IF (tokens.count != indx) THEN
p_error('} should end the JSON object', tokens(indx));
p_error(lastToken||' should end the last token in the JSON string', tokens(indx));
END IF;

RETURN obj;
END parser;
RETURN nodes;
END parse;

----------------------------------------------------------
-- parse_any
-- parse_object
--
FUNCTION parse_any(str CLOB) RETURN /*yyy json_value*/json_nodes
FUNCTION parse_object(str CLOB) RETURN json_nodes
IS
jsrc json_src;
tokens lTokens;
--yyy obj json_list;
obj json_array := json_array();
indx PLS_INTEGER := 1;
BEGIN
updateDecimalPoint();
jsrc := prepareClob(str);
tokens := lexer(jsrc);

IF (tokens(1).type_name != '{') THEN
raise_application_error(-20101, 'JSON Parser exception - invalid first token = '||tokens(1).type_name);
END IF;

RETURN parse(tokens=>tokens, firstToken=>'{');
END parse_object;

----------------------------------------------------------
-- parse_array
--
FUNCTION parse_array(str CLOB) RETURN json_nodes
IS
jsrc json_src;
tokens lTokens;
BEGIN
debug('parse_any');
updateDecimalPoint();
jsrc := prepareClob(str);
tokens := lexer(jsrc);
tokens(tokens.count+1).type_name := ']';
--yyy obj := parseArr(tokens, indx);
IF (tokens.count != indx) THEN
p_error('] should end the JSON List object', tokens(indx));

IF (tokens(1).type_name != '[') THEN
raise_application_error(-20101, 'JSON Parser exception - invalid first token = '||tokens(1).type_name);
END IF;

RETURN parse(tokens=>tokens, firstToken=>'[');
END parse_array;

----------------------------------------------------------
-- parse_any
--
FUNCTION parse_any(str CLOB) RETURN json_value
IS
firstToken VARCHAR2(1);
jsrc json_src;
tokens lTokens;
value json_value := json_value();
BEGIN
updateDecimalPoint();
jsrc := prepareClob(str);
tokens := lexer(jsrc);

IF (tokens(1).type_name = '{') THEN
firstToken := tokens(1).type_name;
value.typ := 'O';
ELSIF (tokens(1).type_name = '[') THEN
firstToken := tokens(1).type_name;
value.typ := 'A';
ELSE
raise_application_error(-20101, 'JSON Parser exception - invalid first token = '||tokens(1).type_name);
END IF;

--yyy return obj.head();
RETURN NULL;
value.nodes := parse(tokens=>tokens, firstToken=>firstToken);

RETURN value;
END parse_any;

END json_parser;
Expand Down
6 changes: 3 additions & 3 deletions json_parser.pks
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ json_strict BOOLEAN NOT NULL := FALSE;
-- GLOBAL PUBLIC MODULES
----------------------------------------------------------

FUNCTION parser(str CLOB) RETURN json_nodes;
FUNCTION parse_list(str CLOB) RETURN json_nodes;
FUNCTION parse_any(str CLOB) RETURN json_nodes;
FUNCTION parse_object(str CLOB) RETURN json_nodes;
FUNCTION parse_array(str CLOB) RETURN json_nodes;
FUNCTION parse_any(str CLOB) RETURN json_value;

END json_parser;
/
13 changes: 13 additions & 0 deletions json_value.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ BEGIN
RETURN;
END json_value;

----------------------------------------------------------
-- json_value
--
CONSTRUCTOR FUNCTION json_value(SELF IN OUT NOCOPY json_value, theJSONString IN CLOB) RETURN SELF AS RESULT
IS
value json_value := json_value();
BEGIN
value := json_parser.parse_any(theJSONString);
SELF.typ := value.typ;
SELF.nodes := value.nodes;
RETURN;
END json_value;

----------------------------------------------------------
-- get_type
--
Expand Down
1 change: 1 addition & 0 deletions json_value.tps
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ TYPE json_value IS OBJECT

-- Default constructor
CONSTRUCTOR FUNCTION json_value(SELF IN OUT NOCOPY json_value) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION json_value(SELF IN OUT NOCOPY json_value, theJSONString IN CLOB) RETURN SELF AS RESULT,

-- Member getter methods
MEMBER FUNCTION get_type RETURN VARCHAR2,
Expand Down
Loading

0 comments on commit 00d15bf

Please sign in to comment.