Skip to content

Commit d080fb0

Browse files
author
Nikita Glukhov
committed
Add jsonb_canonical()
1 parent 9f4547d commit d080fb0

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
@@ -4208,6 +4208,17 @@ jsonb_pretty(PG_FUNCTION_ARGS)
42084208
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
42094209
}
42104210

4211+
Datum
4212+
jsonb_canonical(PG_FUNCTION_ARGS)
4213+
{
4214+
Jsonb *jb = PG_GETARG_JSONB(0);
4215+
StringInfo str = makeStringInfo();
4216+
4217+
JsonbToCStringCanonical(str, &jb->root, VARSIZE(jb));
4218+
4219+
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
4220+
}
4221+
42114222
/*
42124223
* SQL function jsonb_concat (jsonb, jsonb)
42134224
*

src/include/catalog/pg_proc.dat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9510,6 +9510,9 @@
95109510
{ oid => '3306', descr => 'Indented text from jsonb',
95119511
proname => 'jsonb_pretty', prorettype => 'text', proargtypes => 'jsonb',
95129512
prosrc => 'jsonb_pretty' },
9513+
{ oid => '4035', descr => 'Canonical text from jsonb',
9514+
proname => 'jsonb_canonical', prorettype => 'text',
9515+
proargtypes => 'jsonb', prosrc => 'jsonb_canonical' },
95139516
{ oid => '3579', descr => 'Insert value into a jsonb',
95149517
proname => 'jsonb_insert', prorettype => 'jsonb',
95159518
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
@@ -372,6 +372,8 @@ extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
372372
int estimated_len);
373373
extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
374374
int estimated_len);
375+
extern char *JsonbToCStringCanonical(StringInfo out, JsonbContainer *in,
376+
int estimated_len);
375377
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
376378
extern const char *JsonbTypeName(JsonbValue *jb);
377379

0 commit comments

Comments
 (0)