Skip to content

Commit 28ed5bb

Browse files
author
Nikita Glukhov
committed
Try to preserve formatting for text jsons
1 parent 0ab9809 commit 28ed5bb

File tree

6 files changed

+85
-54
lines changed

6 files changed

+85
-54
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ jsonvContainerOps =
556556
jsonvFindValueInArray,
557557
jsonvGetArrayElement,
558558
jsonvGetArraySize,
559-
JsonbToCString,
559+
JsonbToCStringRaw,
560560
};
561561

562562
JsonValue *

src/backend/utils/adt/jsonb.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,12 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
442442
break;
443443
}
444444

445-
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false);
445+
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false, true);
446446
}
447447

448448
#ifndef JSON_C
449449
/*
450-
* JsonbToCString
450+
* JsonbToCStringRaw
451451
* Converts jsonb value to a C-string.
452452
*
453453
* If 'out' argument is non-null, the resulting C-string is stored inside the
@@ -458,7 +458,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
458458
* if they are converting it to a text* object.
459459
*/
460460
char *
461-
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
461+
JsonbToCStringRaw(StringInfo out, JsonbContainer *in, int estimated_len)
462462
{
463463
return JsonbToCStringWorker(out, in, estimated_len, JsonFormatNormal);
464464
}
@@ -495,6 +495,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
495495
/* If we are indenting, don't add a space after a comma */
496496
int ispaces = format == JsonFormatNormal ? 2 : 1;
497497
bool indent = format == JsonFormatIndented;
498+
bool skipNested = format == JsonFormatNormal;
498499

499500
/*
500501
* Don't indent the very first item. This gets set to the indent flag at
@@ -512,7 +513,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
512513
it = JsonbIteratorInit(in);
513514

514515
while (redo_switch ||
515-
((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
516+
((type = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE))
516517
{
517518
redo_switch = false;
518519
switch (type)
@@ -553,11 +554,14 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
553554
jsonb_put_escaped_value(out, &v);
554555
appendBinaryStringInfo(out, ": ", 2);
555556

556-
type = JsonbIteratorNext(&it, &v, false);
557+
type = JsonbIteratorNext(&it, &v, skipNested);
557558
if (type == WJB_VALUE)
558559
{
559560
first = false;
560-
jsonb_put_escaped_value(out, &v);
561+
if (v.type == jbvBinary)
562+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
563+
else
564+
jsonb_put_escaped_value(out, &v);
561565
}
562566
else
563567
{
@@ -578,7 +582,11 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len,
578582

579583
if (!raw_scalar)
580584
add_indent(out, use_indent, level);
581-
jsonb_put_escaped_value(out, &v);
585+
586+
if (v.type == jbvBinary)
587+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
588+
else
589+
jsonb_put_escaped_value(out, &v);
582590
break;
583591
case WJB_END_ARRAY:
584592
level--;
@@ -903,6 +911,15 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
903911
{
904912
JsonbIteratorToken type;
905913

914+
JsonToJsonValue(jsonb, &jb);
915+
916+
if (result->parseState)
917+
{
918+
pushScalarJsonbValue(&result->parseState, &jb,
919+
false, false);
920+
return;
921+
}
922+
906923
while ((type = JsonbIteratorNext(&it, &jb, false))
907924
!= WJB_DONE)
908925
{
@@ -934,7 +951,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
934951
return;
935952
}
936953

937-
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar);
954+
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar,
955+
true);
938956
}
939957

940958
/*

src/backend/utils/adt/jsonb_util.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ static void appendElement(JsonbParseState *pstate, const JsonbValue *scalarVal);
101101
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
102102
static void uniqueifyJsonbObject(JsonbValue *object);
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 *
@@ -162,7 +163,7 @@ JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
162163
if (IsAJsonbScalar(val))
163164
{
164165
JsonbParseState *pstate = NULL;
165-
val = pushSingleScalarJsonbValue(&pstate, val);
166+
val = pushSingleScalarJsonbValue(&pstate, val, true);
166167
}
167168
else
168169
{
@@ -694,8 +695,8 @@ JsonbParseStateClone(JsonbParseState *state)
694695
* are unpacked before being added to the result.
695696
*/
696697
JsonbValue *
697-
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
698-
const JsonbValue *jbval)
698+
pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
699+
const JsonbValue *jbval, bool unpackBinary)
699700
{
700701
JsonIterator *it;
701702
JsonbValue *res = NULL;
@@ -709,25 +710,29 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
709710
for (i = 0; i < jbval->val.object.nPairs; i++)
710711
{
711712
pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
712-
pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
713+
pushJsonbValueExt(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value, unpackBinary);
713714
}
714715

715716
return pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
716717
}
717718

718719
if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvArray)
719720
{
721+
if (jbval->val.array.rawScalar)
722+
return pushJsonbValue(pstate, seq, &jbval->val.array.elems[0]);
723+
720724
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
725+
721726
for (i = 0; i < jbval->val.array.nElems; i++)
722727
{
723-
pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
728+
pushJsonbValueExt(pstate, WJB_ELEM, &jbval->val.array.elems[i], unpackBinary);
724729
}
725730

726731
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
727732
}
728733

729734
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
730-
jbval->type != jbvBinary)
735+
jbval->type != jbvBinary || !unpackBinary)
731736
{
732737
/* drop through */
733738
return pushJsonbValueScalar(pstate, seq, jbval);
@@ -815,7 +820,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
815820
appendValue(*pstate, scalarVal);
816821
break;
817822
case WJB_ELEM:
818-
Assert(IsAJsonbScalar(scalarVal));
823+
/* Assert(IsAJsonbScalar(scalarVal)); */
819824
appendElement(*pstate, scalarVal);
820825
break;
821826
case WJB_END_OBJECT:
@@ -854,7 +859,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
854859
}
855860

856861
static JsonbValue *
857-
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
862+
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
863+
bool unpackBinary)
858864
{
859865
/* single root scalar */
860866
JsonbValue va;
@@ -864,20 +870,21 @@ pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
864870
va.val.array.nElems = 1;
865871

866872
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, &va);
867-
pushJsonbValue(pstate, WJB_ELEM, jbval);
873+
pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
868874
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
869875
}
870876

871877
static JsonbValue *
872878
pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
873-
bool isKey)
879+
bool isKey, bool unpackBinary)
874880
{
875881
switch ((*pstate)->contVal.type)
876882
{
877883
case jbvArray:
878-
return pushJsonbValue(pstate, WJB_ELEM, jbval);
884+
return pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
879885
case jbvObject:
880-
return pushJsonbValue(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval);
886+
return pushJsonbValueExt(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval,
887+
unpackBinary);
881888
default:
882889
elog(ERROR, "unexpected parent of nested structure");
883890
return NULL;
@@ -886,11 +893,11 @@ pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
886893

887894
JsonbValue *
888895
pushScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
889-
bool isKey)
896+
bool isKey, bool unpackBinary)
890897
{
891898
return *pstate == NULL
892-
? pushSingleScalarJsonbValue(pstate, jbval)
893-
: pushNestedScalarJsonbValue(pstate, jbval, isKey);
899+
? pushSingleScalarJsonbValue(pstate, jbval, unpackBinary)
900+
: pushNestedScalarJsonbValue(pstate, jbval, isKey, unpackBinary);
894901

895902
}
896903

@@ -2198,5 +2205,5 @@ jsonbContainerOps =
21982205
jsonbFindValueInArray,
21992206
jsonbGetArrayElement,
22002207
NULL,
2201-
JsonbToCString,
2208+
JsonbToCStringRaw,
22022209
};

0 commit comments

Comments
 (0)