Skip to content

Commit 525dbbf

Browse files
author
Nikita Glukhov
committed
Add jsonb_canonical()
1 parent 62ae11e commit 525dbbf

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

src/backend/utils/adt/jsonb.c

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

54+
typedef enum
55+
{
56+
JsonFormatCanonical,
57+
JsonFormatNormal,
58+
JsonFormatIndented
59+
} JsonFormat;
60+
5461
typedef struct JsonbAggState
5562
{
5663
JsonbInState *res;
@@ -85,7 +92,8 @@ static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
8592
bool key_scalar);
8693
static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
8794
Oid val_type, bool key_scalar);
88-
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
95+
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in,
96+
int estimated_len, JsonFormat format);
8997
static void add_indent(StringInfo out, bool indent, int level);
9098

9199
/*
@@ -399,7 +407,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
399407
char *
400408
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
401409
{
402-
return JsonbToCStringWorker(out, in, estimated_len, false);
410+
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatNormal);
403411
}
404412

405413
/*
@@ -408,14 +416,21 @@ JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
408416
char *
409417
JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
410418
{
411-
return JsonbToCStringWorker(out, in, estimated_len, true);
419+
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatIndented);
420+
}
421+
422+
char *
423+
JsonbToCStringCanonical(StringInfo out, JsonbContainer *in, int estimated_len)
424+
{
425+
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatCanonical);
412426
}
413427

414428
/*
415429
* common worker for above two functions
416430
*/
417431
static char *
418-
JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
432+
JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
433+
JsonFormat format)
419434
{
420435
bool first = true;
421436
JsonbIterator *it;
@@ -425,7 +440,8 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
425440
bool redo_switch = false;
426441

427442
/* If we are indenting, don't add a space after a comma */
428-
int ispaces = indent ? 1 : 2;
443+
int ispaces = format == JsonFormatNormal ? 2 : 1;
444+
bool indent = format == JsonFormatIndented;
429445

430446
/*
431447
* 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
@@ -4000,6 +4000,17 @@ jsonb_pretty(PG_FUNCTION_ARGS)
40004000
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
40014001
}
40024002

4003+
Datum
4004+
jsonb_canonical(PG_FUNCTION_ARGS)
4005+
{
4006+
Jsonb *jb = PG_GETARG_JSONB(0);
4007+
StringInfo str = makeStringInfo();
4008+
4009+
JsonbToCStringCanonical(str, &jb->root, VARSIZE(jb));
4010+
4011+
PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
4012+
}
4013+
40034014
/*
40044015
* SQL function jsonb_concat (jsonb, jsonb)
40054016
*

src/include/catalog/pg_proc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5013,6 +5013,9 @@ DATA(insert OID = 3305 ( jsonb_set PGNSP PGUID 12 1 0 0 0 f f f f t f i s 4
50135013
DESCR("Set part of a jsonb");
50145014
DATA(insert OID = 3306 ( jsonb_pretty PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 25 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_pretty _null_ _null_ _null_ ));
50155015
DESCR("Indented text from jsonb");
5016+
DATA(insert OID = 3416 ( jsonb_canonical PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 25 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_canonical _null_ _null_ _null_ ));
5017+
DESCR("Canonical text from jsonb");
5018+
50165019
DATA(insert OID = 3579 ( jsonb_insert PGNSP PGUID 12 1 0 0 0 f f f f t f i s 4 0 3802 "3802 1009 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_insert _null_ _null_ _null_ ));
50175020
DESCR("Insert value into a jsonb");
50185021
/* txid */

src/include/utils/jsonb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
344344
int estimated_len);
345345
extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
346346
int estimated_len);
347-
347+
extern char *JsonbToCStringCanonical(StringInfo out, JsonbContainer *in,
348+
int estimated_len);
348349

349350
#endif /* __JSONB_H__ */

0 commit comments

Comments
 (0)