Skip to content

Commit 1c7856d

Browse files
author
Nikita Glukhov
committed
Add jsonb_canonical()
1 parent c85806e commit 1c7856d

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

src/backend/utils/adt/jsonb.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ typedef enum /* type categories for datum_to_jsonb */
5252
JSONBTYPE_OTHER /* all else */
5353
} JsonbTypeCategory;
5454

55+
typedef enum
56+
{
57+
JsonFormatCanonical,
58+
JsonFormatNormal,
59+
JsonFormatIndented
60+
} JsonFormat;
61+
5562
typedef struct JsonbAggState
5663
{
5764
JsonbInState *res;
@@ -86,7 +93,8 @@ static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
8693
bool key_scalar);
8794
static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
8895
Oid val_type, bool key_scalar);
89-
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
96+
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in,
97+
int estimated_len, JsonFormat format);
9098
static void add_indent(StringInfo out, bool indent, int level);
9199

92100
/*
@@ -431,7 +439,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
431439
char *
432440
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
433441
{
434-
return JsonbToCStringWorker(out, in, estimated_len, false);
442+
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatNormal);
435443
}
436444

437445
/*
@@ -440,14 +448,21 @@ JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
440448
char *
441449
JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
442450
{
443-
return JsonbToCStringWorker(out, in, estimated_len, true);
451+
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatIndented);
452+
}
453+
454+
char *
455+
JsonbToCStringCanonical(StringInfo out, JsonbContainer *in, int estimated_len)
456+
{
457+
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatCanonical);
444458
}
445459

446460
/*
447461
* common worker for above two functions
448462
*/
449463
static char *
450-
JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
464+
JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
465+
JsonFormat format)
451466
{
452467
bool first = true;
453468
JsonbIterator *it;
@@ -457,7 +472,8 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
457472
bool redo_switch = false;
458473

459474
/* If we are indenting, don't add a space after a comma */
460-
int ispaces = indent ? 1 : 2;
475+
int ispaces = format == JsonFormatNormal ? 2 : 1;
476+
bool indent = format == JsonFormatIndented;
461477

462478
/*
463479
* Don't indent the very first item. This gets set to the indent flag at

src/backend/utils/adt/jsonfuncs.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4307,6 +4307,17 @@ jsonb_pretty(PG_FUNCTION_ARGS)
43074307
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
43084308
}
43094309

4310+
Datum
4311+
jsonb_canonical(PG_FUNCTION_ARGS)
4312+
{
4313+
Jsonb *jb = PG_GETARG_JSONB(0);
4314+
StringInfo str = makeStringInfo();
4315+
4316+
JsonbToCStringCanonical(str, &jb->root, VARSIZE(jb));
4317+
4318+
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
4319+
}
4320+
43104321
/*
43114322
* SQL function jsonb_concat (jsonb, jsonb)
43124323
*

src/include/catalog/pg_proc.dat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9706,6 +9706,9 @@
97069706
{ oid => '3306', descr => 'Indented text from jsonb',
97079707
proname => 'jsonb_pretty', prorettype => 'text', proargtypes => 'jsonb',
97089708
prosrc => 'jsonb_pretty' },
9709+
{ oid => '2137', descr => 'Canonical text from jsonb',
9710+
proname => 'jsonb_canonical', prorettype => 'text',
9711+
proargtypes => 'jsonb', prosrc => 'jsonb_canonical' },
97099712
{ oid => '3579', descr => 'Insert value into a jsonb',
97109713
proname => 'jsonb_insert', prorettype => 'jsonb',
97119714
proargtypes => 'jsonb _text jsonb bool', prosrc => 'jsonb_insert' },

src/include/utils/jsonb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,8 @@ extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
373373
int estimated_len);
374374
extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
375375
int estimated_len);
376+
extern char *JsonbToCStringCanonical(StringInfo out, JsonbContainer *in,
377+
int estimated_len);
376378
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
377379
extern const char *JsonbTypeName(JsonbValue *jb);
378380

0 commit comments

Comments
 (0)