From ff3e91ad23d632ac717a857107959a8de8068598 Mon Sep 17 00:00:00 2001 From: Shihao Date: Fri, 18 Sep 2026 23:14:30 -0400 Subject: [PATCH 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. It took 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 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 728392f436f..779baa2e02b 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -3710,8 +3710,11 @@ 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)