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