aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/jsonb.c')
-rw-r--r--src/backend/utils/adt/jsonb.c81
1 files changed, 70 insertions, 11 deletions
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 7e2c359b219..bccc6696a4f 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -85,6 +85,8 @@ static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
Oid val_type, bool key_scalar);
static JsonbParseState * clone_parse_state(JsonbParseState * state);
+static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
+static void add_indent(StringInfo out, bool indent, int level);
/*
* jsonb type input function
@@ -422,12 +424,39 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
char *
JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
{
+ return JsonbToCStringWorker(out, in, estimated_len, false);
+}
+
+/*
+ * same thing but with indentation turned on
+ */
+char *
+JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
+{
+ return JsonbToCStringWorker(out, in, estimated_len, true);
+}
+
+/*
+ * common worker for above two functions
+ */
+static char *
+JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
+{
bool first = true;
JsonbIterator *it;
JsonbIteratorToken type = WJB_DONE;
JsonbValue v;
int level = 0;
bool redo_switch = false;
+ /* If we are indenting, don't add a space after a comma */
+ int ispaces = indent ? 1 : 2;
+ /*
+ * Don't indent the very first item. This gets set to the indent flag
+ * at the bottom of the loop.
+ */
+ bool use_indent = false;
+ bool raw_scalar = false;
+ bool last_was_key = false;
if (out == NULL)
out = makeStringInfo();
@@ -444,26 +473,36 @@ JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
{
case WJB_BEGIN_ARRAY:
if (!first)
- appendBinaryStringInfo(out, ", ", 2);
- first = true;
+ appendBinaryStringInfo(out, ", ", ispaces);
if (!v.val.array.rawScalar)
- appendStringInfoChar(out, '[');
+ {
+ add_indent(out, use_indent && !last_was_key, level);
+ appendStringInfoCharMacro(out, '[');
+ }
+ else
+ raw_scalar = true;
+
+ first = true;
level++;
break;
case WJB_BEGIN_OBJECT:
if (!first)
- appendBinaryStringInfo(out, ", ", 2);
- first = true;
+ appendBinaryStringInfo(out, ", ", ispaces);
+
+ add_indent(out, use_indent && !last_was_key, level);
appendStringInfoCharMacro(out, '{');
+ first = true;
level++;
break;
case WJB_KEY:
if (!first)
- appendBinaryStringInfo(out, ", ", 2);
+ appendBinaryStringInfo(out, ", ", ispaces);
first = true;
+ add_indent(out, use_indent, level);
+
/* json rules guarantee this is a string */
jsonb_put_escaped_value(out, &v);
appendBinaryStringInfo(out, ": ", 2);
@@ -488,26 +527,33 @@ JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
break;
case WJB_ELEM:
if (!first)
- appendBinaryStringInfo(out, ", ", 2);
- else
- first = false;
+ appendBinaryStringInfo(out, ", ", ispaces);
+ first = false;
+ if (! raw_scalar)
+ add_indent(out, use_indent, level);
jsonb_put_escaped_value(out, &v);
break;
case WJB_END_ARRAY:
level--;
- if (!v.val.array.rawScalar)
- appendStringInfoChar(out, ']');
+ if (! raw_scalar)
+ {
+ add_indent(out, use_indent, level);
+ appendStringInfoCharMacro(out, ']');
+ }
first = false;
break;
case WJB_END_OBJECT:
level--;
+ add_indent(out, use_indent, level);
appendStringInfoCharMacro(out, '}');
first = false;
break;
default:
elog(ERROR, "unknown jsonb iterator token type");
}
+ use_indent = indent;
+ last_was_key = redo_switch;
}
Assert(level == 0);
@@ -515,6 +561,19 @@ JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
return out->data;
}
+static void
+add_indent(StringInfo out, bool indent, int level)
+{
+ if (indent)
+ {
+ int i;
+
+ appendStringInfoCharMacro(out, '\n');
+ for (i = 0; i < level; i++)
+ appendBinaryStringInfo(out, " ", 4);
+ }
+}
+
/*
* Determine how we want to render values of a given type in datum_to_jsonb.