On Mon, May 2, 2016 at 4:04 PM, Andrew Dunstan <and...@dunslane.net> wrote:

>
> On 05/02/2016 04:56 AM, Shulgin, Oleksandr wrote:
>
>> On Sun, May 1, 2016 at 3:22 AM, Andrew Dunstan <and...@dunslane.net
>> <mailto:and...@dunslane.net>> 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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to