Skip to content

Commit e74d1fe

Browse files
author
Nikita Glukhov
committed
Add jsonb_canonical()
1 parent af50a7c commit e74d1fe

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
@@ -9512,6 +9512,9 @@
95129512
{ oid => '3306', descr => 'Indented text from jsonb',
95139513
proname => 'jsonb_pretty', prorettype => 'text', proargtypes => 'jsonb',
95149514
prosrc => 'jsonb_pretty' },
9515+
{ oid => '4035', descr => 'Canonical text from jsonb',
9516+
proname => 'jsonb_canonical', prorettype => 'text',
9517+
proargtypes => 'jsonb', prosrc => 'jsonb_canonical' },
95159518
{ oid => '3579', descr => 'Insert value into a jsonb',
95169519
proname => 'jsonb_insert', prorettype => 'jsonb',
95179520
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy