Skip to content

Commit 63efa8e

Browse files
author
Nikita Glukhov
committed
Try to preserve formatting for text jsons
1 parent 0c2b409 commit 63efa8e

File tree

6 files changed

+57
-30
lines changed

6 files changed

+57
-30
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: 18 additions & 15 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 *
@@ -163,7 +164,7 @@ JsonValueFlatten(const JsonValue *val, JsonValueEncoder encoder,
163164
if (IsAJsonbScalar(val))
164165
{
165166
JsonbParseState *pstate = NULL;
166-
val = pushSingleScalarJsonbValue(&pstate, val);
167+
val = pushSingleScalarJsonbValue(&pstate, val, true);
167168
}
168169
else
169170
{
@@ -695,16 +696,16 @@ JsonbParseStateClone(JsonbParseState *state)
695696
* are unpacked before being added to the result.
696697
*/
697698
JsonbValue *
698-
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
699-
const JsonbValue *jbval)
699+
pushJsonbValueExt(JsonbParseState **pstate, JsonbIteratorToken seq,
700+
const JsonbValue *jbval, bool unpackBinary)
700701
{
701702
JsonIterator *it;
702703
JsonbValue *res = NULL;
703704
JsonbValue v;
704705
JsonbIteratorToken tok;
705706

706707
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
707-
jbval->type != jbvBinary)
708+
jbval->type != jbvBinary || !unpackBinary)
708709
{
709710
/* drop through */
710711
return pushJsonbValueScalar(pstate, seq, jbval);
@@ -772,7 +773,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
772773
appendValue(*pstate, scalarVal);
773774
break;
774775
case WJB_ELEM:
775-
Assert(IsAJsonbScalar(scalarVal));
776+
/* Assert(IsAJsonbScalar(scalarVal)); */
776777
appendElement(*pstate, scalarVal);
777778
break;
778779
case WJB_END_OBJECT:
@@ -811,7 +812,8 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
811812
}
812813

813814
static JsonbValue *
814-
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
815+
pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
816+
bool unpackBinary)
815817
{
816818
/* single root scalar */
817819
JsonbValue va;
@@ -821,20 +823,21 @@ pushSingleScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval)
821823
va.val.array.nElems = 1;
822824

823825
pushJsonbValue(pstate, WJB_BEGIN_ARRAY, &va);
824-
pushJsonbValue(pstate, WJB_ELEM, jbval);
826+
pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
825827
return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
826828
}
827829

828830
static JsonbValue *
829831
pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
830-
bool isKey)
832+
bool isKey, bool unpackBinary)
831833
{
832834
switch ((*pstate)->contVal.type)
833835
{
834836
case jbvArray:
835-
return pushJsonbValue(pstate, WJB_ELEM, jbval);
837+
return pushJsonbValueExt(pstate, WJB_ELEM, jbval, unpackBinary);
836838
case jbvObject:
837-
return pushJsonbValue(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval);
839+
return pushJsonbValueExt(pstate, isKey ? WJB_KEY : WJB_VALUE, jbval,
840+
unpackBinary);
838841
default:
839842
elog(ERROR, "unexpected parent of nested structure");
840843
return NULL;
@@ -843,11 +846,11 @@ pushNestedScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
843846

844847
JsonbValue *
845848
pushScalarJsonbValue(JsonbParseState **pstate, const JsonbValue *jbval,
846-
bool isKey)
849+
bool isKey, bool unpackBinary)
847850
{
848851
return *pstate == NULL
849-
? pushSingleScalarJsonbValue(pstate, jbval)
850-
: pushNestedScalarJsonbValue(pstate, jbval, isKey);
852+
? pushSingleScalarJsonbValue(pstate, jbval, unpackBinary)
853+
: pushNestedScalarJsonbValue(pstate, jbval, isKey, unpackBinary);
851854

852855
}
853856

@@ -2155,5 +2158,5 @@ jsonbContainerOps =
21552158
jsonbFindValueInArray,
21562159
jsonbGetArrayElement,
21572160
NULL,
2158-
JsonbToCString,
2161+
JsonbToCStringRaw,
21592162
};

src/backend/utils/adt/jsonfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4278,7 +4278,7 @@ addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb)
42784278
Assert(v.type == jbvArray);
42794279
(void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
42804280

4281-
(void) pushScalarJsonbValue(jbps, &v, false);
4281+
(void) pushScalarJsonbValue(jbps, &v, false, true);
42824282
}
42834283
else
42844284
{

src/include/utils/json_generic.h

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

300300

301-
extern char *JsonbToCString(StringInfo out, JsonContainer *in,
301+
extern char *JsonbToCStringRaw(StringInfo out, JsonContainer *in,
302302
int estimated_len);
303303
extern char *JsonbToCStringIndent(StringInfo out, JsonContainer *in,
304304
int estimated_len);
@@ -310,6 +310,9 @@ extern char *JsonbToCStringCanonical(StringInfo out, JsonContainer *in,
310310
#define JsonToCStringExt(out, in, estimated_len) \
311311
((*(in)->ops->toString)(out, in, estimated_len))
312312

313+
#define JsonbToCString(out, in, estimated_len) \
314+
JsonToCStringExt(out, in, estimated_len)
315+
313316
extern JsonValue *jsonFindKeyInObject(JsonContainer *obj, const char *key, int len);
314317
extern JsonValue *jsonFindLastKeyInObject(JsonContainer *obj, const char *key, int len);
315318
extern JsonValue *jsonFindValueInArray(JsonContainer *array, const JsonValue *elem);

src/include/utils/jsonb.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,14 +354,17 @@ extern JsonbValue *findJsonbValueFromContainer(const JsonbContainer *sheader,
354354
extern JsonbValue *getKeyJsonValueFromContainer(const struct JsonContainerData *container,
355355
const char *keyVal, int keyLen,
356356
JsonbValue *res);
357-
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
358-
JsonbIteratorToken seq,
359-
const JsonbValue *jbval);
357+
extern JsonbValue *pushJsonbValueExt(JsonbParseState **pstate,
358+
JsonbIteratorToken seq,
359+
const JsonbValue *jbVal,
360+
bool unpackBinary);
361+
#define pushJsonbValue(pstate, seq, jv) pushJsonbValueExt(pstate, seq, jv, true)
360362
extern JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
361363
JsonbIteratorToken seq,
362364
const JsonbValue *scalarVal);
363365
extern JsonbValue *pushScalarJsonbValue(JsonbParseState **pstate,
364-
const JsonbValue *jbval, bool isKey);
366+
const JsonbValue *jbval, bool isKey,
367+
bool unpackBinary);
365368
extern JsonbParseState *JsonbParseStateClone(JsonbParseState *state);
366369
typedef struct JsonIteratorData JsonIterator;
367370
extern JsonbIteratorToken JsonbIteratorNext(JsonIterator **it, JsonbValue *val,

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