From c6b476cb87d3d137d6d3c37efff6f0750aff9e17 Mon Sep 17 00:00:00 2001 From: Dieter Oberkofler Date: Mon, 9 Mar 2020 19:35:03 +0100 Subject: [PATCH] Added output configuration option `newline_char` for the end of line style and `indentation_char` for the identation style. --- CHANGELOG.md | 8 +++++++- json_utils.pkb | 34 +++++++++++++++++++--------------- json_utils.pks | 36 +++++++++++++++++++++++++----------- unittest/json_ut.pkb | 35 +++++++++++++++++++---------------- 4 files changed, 70 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 390f55f..e4782a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed +## [0.7.0] - 2020-03-09 + +### Changed +- Added output configuration option `newline_char` for the end of line style and `indentation_char` for the identation style. + + ## [0.6.0] - 2020-03-09 ### Changed -- Added api `get_default_options`, `get_options` and `set_options` to `json_utils`package to configure (`Pretty`, `AsciiOutput` and `EscapeSolitus`) the output. +- Added api `get_default_options`, `get_options` and `set_options` to `json_utils`package to configure (`Pretty`, `ascii_output` and `escape_solitus`) the output. - Added support for formatted (pretty) json output with the option `Pretty`. diff --git a/json_utils.pkb b/json_utils.pkb index 186f928..2c287fa 100644 --- a/json_utils.pkb +++ b/json_utils.pkb @@ -4,10 +4,6 @@ IS outputOptions OutputOptionsType; -NEW_LINE CONSTANT VARCHAR2(2) := ' -'; -INDENTATION_CHARACTER CONSTANT VARCHAR2(1) := ' '; - PROCEDURE copySubNodes(theTarget IN OUT NOCOPY jsonNodes, theFirstID IN OUT NOCOPY BINARY_INTEGER, theParentID IN BINARY_INTEGER, theSource IN jsonNodes, theFirstSourceID IN BINARY_INTEGER); FUNCTION boolean_to_json(theBoolean IN NUMBER) RETURN VARCHAR2; FUNCTION number_to_json(theNumber IN NUMBER) RETURN VARCHAR2; @@ -39,6 +35,14 @@ END get_options; PROCEDURE set_options(theOptions IN outputOptionsType) IS BEGIN + IF (theOptions.newline_char NOT IN (EOL_LF, EOL_CR, EOL_CRLF)) THEN + raise_application_error(-20100, 'Invalid newline style. Use EOL constant', TRUE); + END IF; + + IF (theOptions.indentation_char NOT IN (IND_TAB, IND_SPACE_1, IND_SPACE_2, IND_SPACE_3, IND_SPACE_4)) THEN + raise_application_error(-20100, 'Invalid indentation style. Use IND constant', TRUE); + END IF; + outputOptions := theOptions; END set_options; @@ -540,7 +544,7 @@ BEGIN -- Add the property name IF (aNode.nam IS NOT NULL) THEN PRAGMA INLINE (escape, 'YES'); - aName := GAP || '"' || escape(theString=>aNode.nam, theAsciiOutput=>outputOptions.AsciiOutput, theEscapeSolitus=>outputOptions.EscapeSolitus) || '":'; + aName := GAP || '"' || escape(theString=>aNode.nam, theAsciiOutput=>outputOptions.ascii_output, theEscapeSolitus=>outputOptions.escape_solitus) || '":'; IF (outputOptions.Pretty) THEN aName := aName || ' '; END IF; @@ -558,13 +562,13 @@ BEGIN WHEN json_utils.NODE_TYPE_STRING THEN PRAGMA INLINE (escape, 'YES'); - json_utils.add_string(theLobBuf=>theLobBuf, theStrBuf=>theStrBuf, theValue=>GAP || '"' || escape(theString=>aNode.str, theAsciiOutput=>outputOptions.AsciiOutput, theEscapeSolitus=>outputOptions.EscapeSolitus) || '"'); + json_utils.add_string(theLobBuf=>theLobBuf, theStrBuf=>theStrBuf, theValue=>GAP || '"' || escape(theString=>aNode.str, theAsciiOutput=>outputOptions.ascii_output, theEscapeSolitus=>outputOptions.escape_solitus) || '"'); WHEN json_utils.NODE_TYPE_LOB THEN PRAGMA INLINE (add_string, 'YES'); json_utils.add_string(theLobBuf=>theLobBuf, theStrBuf=>theStrBuf, theValue=>GAP || '"'); PRAGMA INLINE (escapeLOB, 'YES'); - escapeLOB(theInputLob=>aNode.lob, theLobBuf=>theLobBuf, theStrBuf=>theStrBuf, theAsciiOutput=>outputOptions.AsciiOutput, theEscapeSolitus=>outputOptions.EscapeSolitus); + escapeLOB(theInputLob=>aNode.lob, theLobBuf=>theLobBuf, theStrBuf=>theStrBuf, theAsciiOutput=>outputOptions.ascii_output, theEscapeSolitus=>outputOptions.escape_solitus); PRAGMA INLINE (add_string, 'YES'); json_utils.add_string(theLobBuf=>theLobBuf, theStrBuf=>theStrBuf, theValue=>'"'); @@ -604,16 +608,16 @@ IS BEGIN -- open bracket { IF (outputOptions.Pretty) THEN - aBracket := '{' || NEW_LINE; + aBracket := '{' || outputOptions.newline_char; ELSE aBracket := '{'; END IF; PRAGMA INLINE (add_string, 'YES'); json_utils.add_string(theLobBuf, theStrBuf, aBracket); - + -- compute the delimiter IF (outputOptions.Pretty) THEN - aDelimiter := ',' || NEW_LINE; + aDelimiter := ',' || outputOptions.newline_char; ELSE aDelimiter := ','; END IF; @@ -637,7 +641,7 @@ BEGIN -- close bracket } IF (outputOptions.Pretty) THEN - aBracket := NEW_LINE || GAP || '}'; + aBracket := outputOptions.newline_char || GAP || '}'; ELSE aBracket := GAP || '}'; END IF; @@ -664,7 +668,7 @@ IS BEGIN -- open bracket { IF (outputOptions.Pretty) THEN - aBracket := '[' || NEW_LINE; + aBracket := '[' || outputOptions.newline_char; ELSE aBracket := '['; END IF; @@ -673,7 +677,7 @@ BEGIN -- compute the delimiter IF (outputOptions.Pretty) THEN - aDelimiter := ',' || NEW_LINE; + aDelimiter := ',' || outputOptions.newline_char; ELSE aDelimiter := ','; END IF; @@ -697,7 +701,7 @@ BEGIN -- close bracket } IF (outputOptions.Pretty) THEN - aBracket := NEW_LINE || GAP || ']'; + aBracket := outputOptions.newline_char || GAP || ']'; ELSE aBracket := GAP || ']'; END IF; @@ -777,7 +781,7 @@ FUNCTION get_gap(theIndentation IN INTEGER) RETURN VARCHAR2 IS BEGIN IF (outputOptions.Pretty) THEN - RETURN RPAD(INDENTATION_CHARACTER, theIndentation, INDENTATION_CHARACTER); + RETURN RPAD(outputOptions.indentation_char, theIndentation, outputOptions.indentation_char); ELSE RETURN ''; END IF; diff --git a/json_utils.pks b/json_utils.pks index b6cb1b5..4d9df69 100644 --- a/json_utils.pks +++ b/json_utils.pks @@ -2,23 +2,37 @@ CREATE OR REPLACE PACKAGE json_utils IS +-- indentation styles +IND_TAB CONSTANT VARCHAR2(1 CHAR) := CHR(9); +IND_SPACE_1 CONSTANT VARCHAR2(1 CHAR) := ' '; +IND_SPACE_2 CONSTANT VARCHAR2(2 CHAR) := ' '; +IND_SPACE_3 CONSTANT VARCHAR2(3 CHAR) := ' '; +IND_SPACE_4 CONSTANT VARCHAR2(4 CHAR) := ' '; + +-- end of line styles +EOL_LF CONSTANT VARCHAR2(1 CHAR) := CHR(10); -- macos +EOL_CR CONSTANT VARCHAR2(1 CHAR) := CHR(13); -- linux +EOL_CRLF CONSTANT VARCHAR2(2 CHAR) := EOL_CR || EOL_LF; -- windows + -- output options TYPE outputOptionsType IS RECORD ( - Pretty BOOLEAN DEFAULT FALSE, - AsciiOutput BOOLEAN DEFAULT TRUE, - EscapeSolitus BOOLEAN DEFAULT FALSE + pretty BOOLEAN DEFAULT FALSE, + newline_char VARCHAR2(2 CHAR) DEFAULT EOL_CRLF, + indentation_char VARCHAR2(4 CHAR) DEFAULT IND_TAB, + ascii_output BOOLEAN DEFAULT TRUE, + escape_solitus BOOLEAN DEFAULT FALSE ); -- node types -NODE_TYPE_NULL CONSTANT VARCHAR2(1) := '0'; -NODE_TYPE_STRING CONSTANT VARCHAR2(1) := 'S'; -NODE_TYPE_LOB CONSTANT VARCHAR2(1) := 'L'; -NODE_TYPE_NUMBER CONSTANT VARCHAR2(1) := 'N'; -NODE_TYPE_DATE CONSTANT VARCHAR2(1) := 'D'; -NODE_TYPE_BOOLEAN CONSTANT VARCHAR2(1) := 'B'; -NODE_TYPE_OBJECT CONSTANT VARCHAR2(1) := 'O'; -NODE_TYPE_ARRAY CONSTANT VARCHAR2(1) := 'A'; +NODE_TYPE_NULL CONSTANT VARCHAR2(1 CHAR) := '0'; +NODE_TYPE_STRING CONSTANT VARCHAR2(1 CHAR) := 'S'; +NODE_TYPE_LOB CONSTANT VARCHAR2(1 CHAR) := 'L'; +NODE_TYPE_NUMBER CONSTANT VARCHAR2(1 CHAR) := 'N'; +NODE_TYPE_DATE CONSTANT VARCHAR2(1 CHAR) := 'D'; +NODE_TYPE_BOOLEAN CONSTANT VARCHAR2(1 CHAR) := 'B'; +NODE_TYPE_OBJECT CONSTANT VARCHAR2(1 CHAR) := 'O'; +NODE_TYPE_ARRAY CONSTANT VARCHAR2(1 CHAR) := 'A'; ---------------------------------------------------------- -- get_default_options diff --git a/unittest/json_ut.pkb b/unittest/json_ut.pkb index 75f7b3e..c494e36 100644 --- a/unittest/json_ut.pkb +++ b/unittest/json_ut.pkb @@ -1363,28 +1363,14 @@ END UT_BigObject; PROCEDURE UT_PrettyOutput IS aOldOptions json_utils.outputOptionsType := json_utils.get_options(); - aOptions json_utils.outputOptionsType := json_utils.get_default_options(); + aOptions json_utils.outputOptionsType := json_utils.get_options(); aObject1 jsonObject := jsonObject(); aObject2 jsonObject := jsonObject(); aArray jsonArray := jsonArray(); aLob CLOB := empty_clob(); - - aResult CLOB := '{ - "o1": { - "a1": [ - 1, - 2, - 3 - ], - "a2": [ - 1, - 2, - 3 - ] - } -}'; + aResult CLOB; BEGIN UT_util.module('UT_PrettyOutput'); @@ -1392,6 +1378,23 @@ BEGIN aOptions.Pretty := TRUE; json_utils.set_options(aOptions); + -- result + aResult := + '{'||aOptions.newline_char|| + aOptions.indentation_char||'"o1": {'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||'"a1": ['||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||aOptions.indentation_char||'1,'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||aOptions.indentation_char||'2,'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||aOptions.indentation_char||'3'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||'],'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||'"a2": ['||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||aOptions.indentation_char||'1,'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||aOptions.indentation_char||'2,'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||aOptions.indentation_char||'3'||aOptions.newline_char|| + aOptions.indentation_char||aOptions.indentation_char||']'||aOptions.newline_char|| + aOptions.indentation_char||'}'||aOptions.newline_char|| + '}'; + -- allocate clob dbms_lob.createtemporary(aLob, TRUE);