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)
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