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"}}');