diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index d1dc87e679f696604f650568b835de5bb29f4369..68132aea4bfe59c2d6155e1d2e63b5ffb5cedbae 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -1869,10 +1869,10 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
 	if (PG_ARGISNULL(0))
 	{
 		/*
-		 * Make this StringInfo in a context where it will persist for the
-		 * duration off the aggregate call. It's only needed for this initial
-		 * piece, as the StringInfo routines make sure they use the right
-		 * context to enlarge the object if necessary.
+		 * Make the StringInfo in a context where it will persist for the
+		 * duration of the aggregate call. Switching context is only needed
+		 * for this initial step, as the StringInfo routines make sure they
+		 * use the right context to enlarge the object if necessary.
 		 */
 		oldcontext = MemoryContextSwitchTo(aggcontext);
 		state = makeStringInfo();
@@ -1886,56 +1886,43 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
 		appendStringInfoString(state, ", ");
 	}
 
-	if (PG_ARGISNULL(1))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("field name must not be null")));
-
-	val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
-
 	/*
-	 * turn a constant (more or less literal) value that's of unknown type
-	 * into text. Unknowns come in as a cstring pointer.
+	 * Note: since json_object_agg() is declared as taking type "any", the
+	 * parser will not do any type conversion on unknown-type literals (that
+	 * is, undecorated strings or NULLs).  Such values will arrive here as
+	 * type UNKNOWN, which fortunately does not matter to us, since
+	 * unknownout() works fine.
 	 */
-	if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, 1))
-	{
-		val_type = TEXTOID;
-		arg = CStringGetTextDatum(PG_GETARG_POINTER(1));
-	}
-	else
-	{
-		arg = PG_GETARG_DATUM(1);
-	}
+	val_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
 
-	if (val_type == InvalidOid || val_type == UNKNOWNOID)
+	if (val_type == InvalidOid)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("could not determine data type for argument %d", 1)));
 
+	if (PG_ARGISNULL(1))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("field name must not be null")));
+
+	arg = PG_GETARG_DATUM(1);
+
 	add_json(arg, false, state, val_type, true);
 
 	appendStringInfoString(state, " : ");
 
 	val_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
-	/* see comments above */
-	if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, 2))
-	{
-		val_type = TEXTOID;
-		if (PG_ARGISNULL(2))
-			arg = (Datum) 0;
-		else
-			arg = CStringGetTextDatum(PG_GETARG_POINTER(2));
-	}
-	else
-	{
-		arg = PG_GETARG_DATUM(2);
-	}
 
-	if (val_type == InvalidOid || val_type == UNKNOWNOID)
+	if (val_type == InvalidOid)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("could not determine data type for argument %d", 2)));
 
+	if (PG_ARGISNULL(2))
+		arg = (Datum) 0;
+	else
+		arg = PG_GETARG_DATUM(2);
+
 	add_json(arg, PG_ARGISNULL(2), state, val_type, false);
 
 	PG_RETURN_POINTER(state);
@@ -1972,7 +1959,7 @@ json_build_object(PG_FUNCTION_ARGS)
 	int			nargs = PG_NARGS();
 	int			i;
 	Datum		arg;
-	char	   *sep = "";
+	const char *sep = "";
 	StringInfo	result;
 	Oid			val_type;
 
@@ -1988,60 +1975,51 @@ json_build_object(PG_FUNCTION_ARGS)
 
 	for (i = 0; i < nargs; i += 2)
 	{
+		/*
+		 * Note: since json_build_object() is declared as taking type "any",
+		 * the parser will not do any type conversion on unknown-type literals
+		 * (that is, undecorated strings or NULLs).  Such values will arrive
+		 * here as type UNKNOWN, which fortunately does not matter to us,
+		 * since unknownout() works fine.
+		 */
+		appendStringInfoString(result, sep);
+		sep = ", ";
+
 		/* process key */
+		val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
+
+		if (val_type == InvalidOid)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("could not determine data type for argument %d",
+							i + 1)));
 
 		if (PG_ARGISNULL(i))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("argument %d cannot be null", i + 1),
 					 errhint("Object keys should be text.")));
-		val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
 
-		/*
-		 * turn a constant (more or less literal) value that's of unknown type
-		 * into text. Unknowns come in as a cstring pointer.
-		 */
-		if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i))
-		{
-			val_type = TEXTOID;
-			arg = CStringGetTextDatum(PG_GETARG_POINTER(i));
-		}
-		else
-		{
-			arg = PG_GETARG_DATUM(i);
-		}
-		if (val_type == InvalidOid || val_type == UNKNOWNOID)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("could not determine data type for argument %d",
-							i + 1)));
-		appendStringInfoString(result, sep);
-		sep = ", ";
+		arg = PG_GETARG_DATUM(i);
+
 		add_json(arg, false, result, val_type, true);
 
 		appendStringInfoString(result, " : ");
 
 		/* process value */
-
 		val_type = get_fn_expr_argtype(fcinfo->flinfo, i + 1);
-		/* see comments above */
-		if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i + 1))
-		{
-			val_type = TEXTOID;
-			if (PG_ARGISNULL(i + 1))
-				arg = (Datum) 0;
-			else
-				arg = CStringGetTextDatum(PG_GETARG_POINTER(i + 1));
-		}
-		else
-		{
-			arg = PG_GETARG_DATUM(i + 1);
-		}
-		if (val_type == InvalidOid || val_type == UNKNOWNOID)
+
+		if (val_type == InvalidOid)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("could not determine data type for argument %d",
 							i + 2)));
+
+		if (PG_ARGISNULL(i + 1))
+			arg = (Datum) 0;
+		else
+			arg = PG_GETARG_DATUM(i + 1);
+
 		add_json(arg, PG_ARGISNULL(i + 1), result, val_type, false);
 	}
 
@@ -2068,45 +2046,45 @@ json_build_array(PG_FUNCTION_ARGS)
 	int			nargs = PG_NARGS();
 	int			i;
 	Datum		arg;
-	char	   *sep = "";
+	const char *sep = "";
 	StringInfo	result;
 	Oid			val_type;
 
-
 	result = makeStringInfo();
 
 	appendStringInfoChar(result, '[');
 
 	for (i = 0; i < nargs; i++)
 	{
+		/*
+		 * Note: since json_build_array() is declared as taking type "any",
+		 * the parser will not do any type conversion on unknown-type literals
+		 * (that is, undecorated strings or NULLs).  Such values will arrive
+		 * here as type UNKNOWN, which fortunately does not matter to us,
+		 * since unknownout() works fine.
+		 */
+		appendStringInfoString(result, sep);
+		sep = ", ";
+
 		val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
-		arg = PG_GETARG_DATUM(i + 1);
-		/* see comments in json_build_object above */
-		if (val_type == UNKNOWNOID && get_fn_expr_arg_stable(fcinfo->flinfo, i))
-		{
-			val_type = TEXTOID;
-			if (PG_ARGISNULL(i))
-				arg = (Datum) 0;
-			else
-				arg = CStringGetTextDatum(PG_GETARG_POINTER(i));
-		}
-		else
-		{
-			arg = PG_GETARG_DATUM(i);
-		}
-		if (val_type == InvalidOid || val_type == UNKNOWNOID)
+
+		if (val_type == InvalidOid)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("could not determine data type for argument %d",
 							i + 1)));
-		appendStringInfoString(result, sep);
-		sep = ", ";
+
+		if (PG_ARGISNULL(i))
+			arg = (Datum) 0;
+		else
+			arg = PG_GETARG_DATUM(i);
+
 		add_json(arg, PG_ARGISNULL(i), result, val_type, false);
 	}
+
 	appendStringInfoChar(result, ']');
 
 	PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
-
 }
 
 /*