Skip to content

Commit e0336b1

Browse files
author
Nikita Glukhov
committed
Try to preserve formatting for text jsons
1 parent ba0e1c2 commit e0336b1

File tree

6 files changed

+56
-29
lines changed

6 files changed

+56
-29
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ jsonvContainerOps =
551551
jsonvFindValueInArray,
552552
jsonvGetArrayElement,
553553
jsonvGetArraySize,
554-
JsonbToCString,
554+
JsonbToCStringRaw,
555555
};
556556

557557
JsonValue *

src/backend/utils/adt/jsonb.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,12 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
390390
break;
391391
}
392392

393-
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false);
393+
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false, true);
394394
}
395395

396396
#ifndef JSON_C
397397
/*
398-
* JsonbToCString
398+
* JsonbToCStringRaw
399399
* Converts jsonb value to a C-string.
400400
*
401401
* If 'out' argument is non-null, the resulting C-string is stored inside the
@@ -406,7 +406,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
406406
* if they are converting it to a text* object.
407407
*/
408408
char *
409-
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
409+
JsonbToCStringRaw(StringInfo out, JsonbContainer *in, int estimated_len)
410410
{
411411
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatNormal);
412412
}
@@ -443,6 +443,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
443443
/* If we are indenting, don't add a space after a comma */
444444
int ispaces = format == JsonFormatNormal ? 2 : 1;
445445
bool indent = format == JsonFormatIndented;
446+
bool skipNested = format == JsonFormatNormal;
446447

447448
/*
448449
* Don't indent the very first item. This gets set to the indent flag at
@@ -460,7 +461,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
460461
it = JsonbIteratorInit(in);
461462

462463
while (redo_switch ||
463-
((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
464+
((type = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE))
464465
{
465466
redo_switch = false;
466467
switch (type)
@@ -501,11 +502,14 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
501502
jsonb_put_escaped_value(out, &v);
502503
appendBinaryStringInfo(out, ": ", 2);
503504

504-
type = JsonbIteratorNext(&it, &v, false);
505+
type = JsonbIteratorNext(&it, &v, skipNested);
505506
if (type == WJB_VALUE)
506507
{
507508
first = false;
508-
jsonb_put_escaped_value(out, &v);
509+
if (v.type == jbvBinary)
510+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
511+
else
512+
jsonb_put_escaped_value(out, &v);
509513
}
510514
else
511515
{
@@ -526,7 +530,11 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
526530

527531
if (!raw_scalar)
528532
add_indent(out, use_indent, level);
529-
jsonb_put_escaped_value(out, &v);
533+
534+
if (v.type == jbvBinary)
535+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
536+
else
537+
jsonb_put_escaped_value(out, &v);
530538
break;
531539
case WJB_END_ARRAY:
532540
level--;
@@ -895,6 +903,15 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
895903
{
896904
JsonbIteratorToken type;
897905

906+
JsonToJsonValue(jsonb, &jb);
907+
908+
if (result->parseState)
909+
{
910+
pushScalarJsonbValue(&result->parseState, &jb,
911+
false, false);
912+
return;
913+
}
914+
898915
while ((type = JsonbIteratorNext(&it, &jb, false))
899916
!= WJB_DONE)
900917
{
@@ -926,7 +943,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
926943
return;
927944
}
928945

929-
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar);
946+
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar,
947+
true);
930948
}
931949

932950
/*

src/backend/utils/adt/jsonb_util.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ extern JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
101101
JsonbIteratorToken seq,
102102
const JsonbValue *scalarVal);
103103
static JsonbValue *pushSingleScalarJsonbValue(JsonbParseState **pstate,
104-
const JsonbValue *jbval);
104+
const JsonbValue *jbval,
105+
bool unpackBinary);
105106
static void jsonbInitContainer(JsonContainerData *jc, JsonbContainer *jbc, int len);
106107

107108
JsonValue *
@@ -167,7 +168,7 @@ JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
167168
if (IsAJsonbScalar(val))
168169
{
169170
JsonbParseState *pstate = NULL;
170-
val = pushSingleScalarJsonbValue(&pstate, val);
171+
val = pushSingleScalarJsonbValue(&pstate, val, true);
171172
}
172173
else
173174
{
@@ -667,16 +668,16 @@ JsonbParseStateClone(JsonbParseState *state)
667668
* are unpacked before being added to the result.
668669
*/
669670
JsonbValue *
670-
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
671-
const JsonbValue *jbval)
671+
pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
672+
const JsonbValue *jbval, bool unpackBinary)
672673
{
673674
JsonIterator *it;
674675
JsonbValue *res = NULL;
675676
JsonbValue v;
676677
JsonbIteratorToken tok;
677678

678679
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
679-
jbval->type != jbvBinary)
680+
jbval->type != jbvBinary || !unpackBinary)
680681
{
681682
/* drop through */
682683
return pushJsonbValueScalar(pstate, seq, jbval);
@@ -744,7 +745,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
744745
appendValue(*pstate, scalarVal);
745746
break;
746747
case WJB_ELEM:
747-
Assert(IsAJsonbScalar(scalarVal));
748+
/* Assert(IsAJsonbScalar(scalarVal)); */
748749
appendElement(*pstate, scalarVal);
749750
break;
750751
case WJB_END_OBJECT:
@@ -783,7 +784,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
783784
}
784785

785786
static JsonbValue *
786-
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
787+
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
788+
bool unpackBinary)
787789
{
788790
/* single root scalar */
789791
JsonbValue va;
@@ -793,20 +795,21 @@ pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
793795
va.val.array.nElems = 1;
794796

795797
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, &va);
796-
pushJsonbValue(pstate, WJB_ELEM, jbval);
798+
pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
797799
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
798800
}
799801

800802
static JsonbValue *
801803
pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
802-
bool isKey)
804+
bool isKey, bool unpackBinary)
803805
{
804806
switch ((*pstate)->contVal.type)
805807
{
806808
case jbvArray:
807-
return pushJsonbValue(pstate, WJB_ELEM, jbval);
809+
return pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
808810
case jbvObject:
809-
return pushJsonbValue(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval);
811+
return pushJsonbValueExt(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval,
812+
unpackBinary);
810813
default:
811814
elog(ERROR, "unexpected parent of nested structure");
812815
return NULL;
@@ -815,11 +818,11 @@ pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
815818

816819
JsonbValue *
817820
pushScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
818-
bool isKey)
821+
bool isKey, bool unpackBinary)
819822
{
820823
return *pstate == NULL
821-
? pushSingleScalarJsonbValue(pstate, jbval)
822-
: pushNestedScalarJsonbValue(pstate, jbval, isKey);
824+
? pushSingleScalarJsonbValue(pstate, jbval, unpackBinary)
825+
: pushNestedScalarJsonbValue(pstate, jbval, isKey, unpackBinary);
823826

824827
}
825828

@@ -2064,5 +2067,5 @@ jsonbContainerOps =
20642067
jsonbFindValueInArray,
20652068
jsonbGetArrayElement,
20662069
NULL,
2067-
JsonbToCString,
2070+
JsonbToCStringRaw,
20682071
};

src/backend/utils/adt/jsonfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4052,7 +4052,7 @@ addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
40524052
(void) JsonbIteratorNext(&it, &v, false); /* skip array header */
40534053
(void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
40544054

4055-
(void) pushScalarJsonbValue(jbps, &v, false);
4055+
(void) pushScalarJsonbValue(jbps, &v, false, true);
40564056
}
40574057
else
40584058
{

src/include/utils/json_generic.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ extern JsonValue *JsonContainerExtractKeys(JsonContainer *jsc);
273273
extern JsonValue *JsonValueFromCString(char *json, int len);
274274

275275

276-
extern char *JsonbToCString(StringInfo out, JsonContainer *in,
276+
extern char *JsonbToCStringRaw(StringInfo out, JsonContainer *in,
277277
int estimated_len);
278278
extern char *JsonbToCStringIndent(StringInfo out, JsonContainer *in,
279279
int estimated_len);
@@ -285,6 +285,9 @@ extern char *JsonbToCStringCanonical(StringInfo out, JsonContainer *in,
285285
#define JsonToCStringExt(out, in, estimated_len) \
286286
((*(in)->ops->toString)(out, in, estimated_len))
287287

288+
#define JsonbToCString(out, in, estimated_len) \
289+
JsonToCStringExt(out, in, estimated_len)
290+
288291
extern JsonValue *jsonFindKeyInObject(JsonContainer *obj, const JsonValue *key);
289292
extern JsonValue *jsonFindLastKeyInObject(JsonContainer *obj, const JsonValue *key);
290293
extern JsonValue *jsonFindValueInArray(JsonContainer *array, const JsonValue *elem);

src/include/utils/jsonb.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,14 +329,17 @@ extern int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b);
329329
extern JsonbValue *findJsonbValueFromContainer(const JsonbContainer *sheader,
330330
uint32 flags,
331331
JsonbValue *key);
332-
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
332+
extern JsonbValue *pushJsonbValueExt(JsonbParseState **pstate,
333333
JsonbIteratorToken seq,
334-
const JsonbValue *jbVal);
334+
const JsonbValue *jbVal,
335+
bool unpackBinary);
336+
#define pushJsonbValue(pstate, seq, jv) pushJsonbValueExt(pstate, seq, jv, true)
335337
extern JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
336338
JsonbIteratorToken seq,
337339
const JsonbValue *scalarVal);
338340
extern JsonbValue *pushScalarJsonbValue(JsonbParseState **pstate,
339-
const JsonbValue *jbval, bool isKey);
341+
const JsonbValue *jbval, bool isKey,
342+
bool unpackBinary);
340343
extern JsonbParseState *JsonbParseStateClone(JsonbParseState *state);
341344
typedef struct JsonIteratorData JsonIterator;
342345
extern JsonbIteratorToken JsonbIteratorNext(JsonIterator **it, JsonbValue *val,

0 commit comments

Comments
 (0)