From eb827c81f4eec723bf1b46a6036309f2e89413d0 Mon Sep 17 00:00:00 2001 From: Shihao Date: Fri, 18 Sep 2026 23:14:30 -0400 Subject: [PATCH v1 1/2] Fix JSON_SERIALIZE() with a jsonb argument JSON_SERIALIZE() returns its argument as is and then applies the coercion to the RETURNING type. makeJsonConstructorExpr() built that coercion for a json input, because it picked the input type from the RETURNING format, which is always JSON here. A jsonb argument is not converted before that, so json_out() ran on jsonb data. The result was a few bytes of the jsonb header, which could also be text that is not valid in the server encoding. Build the coercion from the type of the argument instead. This is fixed in the parser, so views and other stored expressions that call JSON_SERIALIZE() on a jsonb value need to be recreated. Reported-by: Dirkjan Bussink Discussion: https://postgr.es/m/03583FE7-A5EE-407C-907D-67865F3F8BFC@gmail.com Backpatch-through: 17 --- src/backend/parser/parse_expr.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 05a6b72d4c9..6baeb1d5b06 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -3710,8 +3710,16 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type, { CaseTestExpr *cte = makeNode(CaseTestExpr); - cte->typeId = returning->format->format_type == JS_FORMAT_JSONB ? - JSONBOID : JSONOID; + if (type == JSCTOR_JSON_SERIALIZE) + cte->typeId = exprType(linitial(args)); + else + cte->typeId = returning->format->format_type == JS_FORMAT_JSONB ? + JSONBOID : JSONOID; cte->typeMod = -1; cte->collation = InvalidOid; -- 2.37.1 (Apple Git-137.1)