On Mon, May 2, 2016 at 4:04 PM, Andrew Dunstan <[email protected]> wrote:
>
> On 05/02/2016 04:56 AM, Shulgin, Oleksandr wrote:
>
>> On Sun, May 1, 2016 at 3:22 AM, Andrew Dunstan <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> On 04/29/2016 06:11 PM, Merlin Moncure wrote:
>>
>> This is a simple matter of removing spaces in the occasional C
>> string
>> literal in the serialization routines and adding a json_pretty
>> function.
>>
>>
>> I spent a few hours on this. See
>> <https://bitbucket.org/adunstan/pgdevel/commits/branch/jsonformat>
>> for WIP - there are three commits. No regression tests yet for the
>> two new functions (json_squash and json_pretty), Otherwise fairly
>> complete. Removing whitespace generation was pretty simple for
>> both json and jsonb.
>>
>>
>> Looks good, thank you!
>>
>> It would make sense IMO to rename FormatState's `indent' field as
>> `pretty': it's being used to add whitespace between the punctuation, not
>> only at start of a line. I'd also move the "if (indent)" check out of
>> add_indent(): just don't call it if no indent is needed.
>>
>> I'll try to play with the patch to produce some regression tests for the
>> new functions.
>>
>>
> It was done the way it was to be as consistent as possible with how it's
> done for jsonb (c.f. jsonb.c:JsonbToCStringWorker and jsonb.c::add_indent).
>
Ah, I see.
Simply taking regression tests for jsonb_pretty() and using them against
json_pretty() revealed a bug with extra indent being added before every
array/object start. Attached patch fixes that and adds the regression
tests.
For json_squash() I've taken the same three test values, for lack of a
better idea at the moment. At least we are testing key order stability and
that no whitespace is spit out.
Regards,
--
Alex
diff --git a/src/backend/utils/adt/jsonfuncs.c
b/src/backend/utils/adt/jsonfuncs.c
new file mode 100644
index d82c9c8..77d8325
*** a/src/backend/utils/adt/jsonfuncs.c
--- b/src/backend/utils/adt/jsonfuncs.c
*************** fmt_object_field_start(void *state, char
*** 3394,3402 ****
escape_json(_state->strval, fname);
! appendStringInfoCharMacro(_state->strval, ':');
! if (_state->indent)
! appendStringInfoCharMacro(_state->strval, ' ');
_state->last_was_key = true;
}
--- 3394,3400 ----
escape_json(_state->strval, fname);
! appendBinaryStringInfo(_state->strval, ": ", _state->indent ? 2 : 1);
_state->last_was_key = true;
}
*************** fmt_array_element_start(void *state, boo
*** 3409,3417 ****
if (!_state->first)
appendStringInfoCharMacro(_state->strval, ',');
_state->first = false;
!
! add_indent(_state->strval, _state->indent, _state->lex->lex_level);
!
}
static void
--- 3407,3413 ----
if (!_state->first)
appendStringInfoCharMacro(_state->strval, ',');
_state->first = false;
! _state->last_was_key = false;
}
static void
*************** fmt_scalar(void *state, char *token, Jso
*** 3419,3424 ****
--- 3415,3424 ----
{
FormatState *_state = (FormatState *) state;
+ if (_state->lex->lex_level > 0)
+ add_indent(_state->strval, _state->indent &&
!_state->last_was_key,
+ _state->lex->lex_level);
+
if (tokentype == JSON_TOKEN_STRING)
escape_json(_state->strval, token);
else
diff --git a/src/test/regress/expected/json.out
b/src/test/regress/expected/json.out
new file mode 100644
index 0c45c64..7af4022
*** a/src/test/regress/expected/json.out
--- b/src/test/regress/expected/json.out
*************** select json_strip_nulls('{"a": {"b": nul
*** 1658,1660 ****
--- 1658,1736 ----
{"a":{},"d":{}}
(1 row)
+ select json_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd":
"test4", "dd2":{"ddd": "test5"}}}');
+ json_pretty
+ ----------------------------
+ { +
+ "a": "test", +
+ "b": [ +
+ 1, +
+ 2, +
+ 3 +
+ ], +
+ "c": "test3", +
+ "d": { +
+ "dd": "test4", +
+ "dd2": { +
+ "ddd": "test5"+
+ } +
+ } +
+ }
+ (1 row)
+
+ select json_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]');
+ json_pretty
+ ---------------------------
+ [ +
+ { +
+ "f1": 1, +
+ "f2": null +
+ }, +
+ 2, +
+ null, +
+ [ +
+ [ +
+ { +
+ "x": true+
+ }, +
+ 6, +
+ 7 +
+ ], +
+ 8 +
+ ], +
+ 3 +
+ ]
+ (1 row)
+
+ select json_pretty('{"a":["b", "c"], "d": {"e":"f"}}');
+ json_pretty
+ ------------------
+ { +
+ "a": [ +
+ "b", +
+ "c" +
+ ], +
+ "d": { +
+ "e": "f"+
+ } +
+ }
+ (1 row)
+
+ select json_squash('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd":
"test4", "dd2":{"ddd": "test5"}}}');
+ json_squash
+
-------------------------------------------------------------------------------
+ {"a":"test","b":[1,2,3],"c":"test3","d":{"dd":"test4","dd2":{"ddd":"test5"}}}
+ (1 row)
+
+ select json_squash('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]');
+ json_squash
+ ----------------------------------------------------
+ [{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]
+ (1 row)
+
+ select json_squash('{"a":["b", "c"], "d": {"e":"f"}}');
+ json_squash
+ -------------------------------
+ {"a":["b","c"],"d":{"e":"f"}}
+ (1 row)
+
diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql
new file mode 100644
index 603288b..f13e0fa
*** a/src/test/regress/sql/json.sql
--- b/src/test/regress/sql/json.sql
*************** select json_strip_nulls('[1,{"a":1,"b":n
*** 545,547 ****
--- 545,556 ----
-- an empty object is not null and should not be stripped
select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }');
+
+
+ select json_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd":
"test4", "dd2":{"ddd": "test5"}}}');
+ select json_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]');
+ select json_pretty('{"a":["b", "c"], "d": {"e":"f"}}');
+
+ select json_squash('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd":
"test4", "dd2":{"ddd": "test5"}}}');
+ select json_squash('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]');
+ select json_squash('{"a":["b", "c"], "d": {"e":"f"}}');
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers