Skip to content

Commit 9951a7b

Browse files
author
Nikita Glukhov
committed
Try to preserve formatting for text jsons
1 parent 4f5929c commit 9951a7b

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
@@ -415,11 +415,11 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
415415
break;
416416
}
417417

418-
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false);
418+
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false, true);
419419
}
420420

421421
/*
422-
* JsonbToCString
422+
* JsonbToCStringRaw
423423
* Converts jsonb value to a C-string.
424424
*
425425
* If 'out' argument is non-null, the resulting C-string is stored inside the
@@ -430,7 +430,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
430430
* if they are converting it to a text* object.
431431
*/
432432
char *
433-
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
433+
JsonbToCStringRaw(StringInfo out, JsonbContainer *in, int estimated_len)
434434
{
435435
return JsonbToCStringWorker(out, in, estimated_len, false);
436436
}
@@ -459,6 +459,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
459459

460460
/* If we are indenting, don't add a space after a comma */
461461
int ispaces = indent ? 1 : 2;
462+
bool skipNested = !indent;
462463

463464
/*
464465
* Don't indent the very first item. This gets set to the indent flag at
@@ -476,7 +477,7 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
476477
it = JsonbIteratorInit(in);
477478

478479
while (redo_switch ||
479-
((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
480+
((type = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE))
480481
{
481482
redo_switch = false;
482483
switch (type)
@@ -517,11 +518,14 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
517518
jsonb_put_escaped_value(out, &v);
518519
appendBinaryStringInfo(out, ": ", 2);
519520

520-
type = JsonbIteratorNext(&it, &v, false);
521+
type = JsonbIteratorNext(&it, &v, skipNested);
521522
if (type == WJB_VALUE)
522523
{
523524
first = false;
524-
jsonb_put_escaped_value(out, &v);
525+
if (v.type == jbvBinary)
526+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
527+
else
528+
jsonb_put_escaped_value(out, &v);
525529
}
526530
else
527531
{
@@ -542,7 +546,11 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool
542546

543547
if (!raw_scalar)
544548
add_indent(out, use_indent, level);
545-
jsonb_put_escaped_value(out, &v);
549+
550+
if (v.type == jbvBinary)
551+
JsonbToCString(out, v.val.binary.data, v.val.binary.len);
552+
else
553+
jsonb_put_escaped_value(out, &v);
546554
break;
547555
case WJB_END_ARRAY:
548556
level--;
@@ -854,6 +862,15 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
854862
{
855863
JsonbIteratorToken type;
856864

865+
JsonToJsonValue(jsonb, &jb);
866+
867+
if (result->parseState)
868+
{
869+
pushScalarJsonbValue(&result->parseState, &jb,
870+
false, false);
871+
return;
872+
}
873+
857874
while ((type = JsonbIteratorNext(&it, &jb, false))
858875
!= WJB_DONE)
859876
{
@@ -885,7 +902,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
885902
return;
886903
}
887904

888-
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar);
905+
result->res = pushScalarJsonbValue(&result->parseState, &jb, key_scalar,
906+
true);
889907
}
890908

891909
/*

src/backend/utils/adt/jsonb_util.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
105105
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys,
106106
bool skip_nulls);
107107
static JsonbValue *pushSingleScalarJsonbValue(JsonbParseState **pstate,
108-
const JsonbValue *jbval);
108+
const JsonbValue *jbval,
109+
bool unpackBinary);
109110
static void jsonbInitContainer(JsonContainerData *jc, JsonbContainer *jbc, int len);
110111

111112
JsonValue *
@@ -166,7 +167,7 @@ JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
166167
if (IsAJsonbScalar(val))
167168
{
168169
JsonbParseState *pstate = NULL;
169-
val = pushSingleScalarJsonbValue(&pstate, val);
170+
val = pushSingleScalarJsonbValue(&pstate, val, true);
170171
}
171172
else
172173
{
@@ -706,8 +707,8 @@ JsonbParseStateSetSkipNulls(JsonbParseState *state, bool skip_nulls)
706707
* are unpacked before being added to the result.
707708
*/
708709
JsonbValue *
709-
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
710-
const JsonbValue *jbval)
710+
pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
711+
const JsonbValue *jbval, bool unpackBinary)
711712
{
712713
JsonIterator *it;
713714
JsonbValue *res = NULL;
@@ -721,25 +722,29 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
721722
for (i = 0; i < jbval->val.object.nPairs; i++)
722723
{
723724
pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
724-
pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
725+
pushJsonbValueExt(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value, unpackBinary);
725726
}
726727

727728
return pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
728729
}
729730

730731
if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvArray)
731732
{
733+
if (jbval->val.array.rawScalar)
734+
return pushJsonbValue(pstate, seq, &jbval->val.array.elems[0]);
735+
732736
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
737+
733738
for (i = 0; i < jbval->val.array.nElems; i++)
734739
{
735-
pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
740+
pushJsonbValueExt(pstate, WJB_ELEM, &jbval->val.array.elems[i], unpackBinary);
736741
}
737742

738743
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
739744
}
740745

741746
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
742-
jbval->type != jbvBinary)
747+
jbval->type != jbvBinary || !unpackBinary)
743748
{
744749
/* drop through */
745750
return pushJsonbValueScalar(pstate, seq, jbval);
@@ -827,7 +832,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
827832
appendValue(*pstate, scalarVal);
828833
break;
829834
case WJB_ELEM:
830-
Assert(IsAJsonbScalar(scalarVal));
835+
/* Assert(IsAJsonbScalar(scalarVal)); */
831836
appendElement(*pstate, scalarVal);
832837
break;
833838
case WJB_END_OBJECT:
@@ -868,7 +873,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
868873
}
869874

870875
static JsonbValue *
871-
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
876+
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
877+
bool unpackBinary)
872878
{
873879
/* single root scalar */
874880
JsonbValue va;
@@ -878,20 +884,21 @@ pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
878884
va.val.array.nElems = 1;
879885

880886
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, &va);
881-
pushJsonbValue(pstate, WJB_ELEM, jbval);
887+
pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
882888
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
883889
}
884890

885891
static JsonbValue *
886892
pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
887-
bool isKey)
893+
bool isKey, bool unpackBinary)
888894
{
889895
switch ((*pstate)->contVal.type)
890896
{
891897
case jbvArray:
892-
return pushJsonbValue(pstate, WJB_ELEM, jbval);
898+
return pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
893899
case jbvObject:
894-
return pushJsonbValue(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval);
900+
return pushJsonbValueExt(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval,
901+
unpackBinary);
895902
default:
896903
elog(ERROR, "unexpected parent of nested structure");
897904
return NULL;
@@ -900,11 +907,11 @@ pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
900907

901908
JsonbValue *
902909
pushScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
903-
bool isKey)
910+
bool isKey, bool unpackBinary)
904911
{
905912
return *pstate == NULL
906-
? pushSingleScalarJsonbValue(pstate, jbval)
907-
: pushNestedScalarJsonbValue(pstate, jbval, isKey);
913+
? pushSingleScalarJsonbValue(pstate, jbval, unpackBinary)
914+
: pushNestedScalarJsonbValue(pstate, jbval, isKey, unpackBinary);
908915

909916
}
910917

@@ -2232,5 +2239,5 @@ jsonbContainerOps =
22322239
jsonbFindValueInArray,
22332240
jsonbGetArrayElement,
22342241
NULL,
2235-
JsonbToCString,
2242+
JsonbToCStringRaw,
22362243
};

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