From c6215cf1fae392fa94a750b6fb1a7594a420f529 Mon Sep 17 00:00:00 2001 From: Gabriel de Tassigny Date: Mon, 10 Aug 2026 11:10:47 +0200 Subject: [PATCH] Fix JSON object/array shape corruption in REST API string replacement json_decode($content, true) in String_Replace::replace_strings() collapsed empty JSON objects ({}) into PHP arrays, which wp_json_encode() then re-serialized as []. Since this runs on every REST API response site-wide, it silently corrupted the shape of any JSON payload containing empty objects - including MCP JSON-RPC handshakes (e.g. Novamira), whose clients validate responses against a strict schema and reject [] where {} is expected. Decode as objects instead of associative arrays so shape survives the round trip. --- php/class-string-replace.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/php/class-string-replace.php b/php/class-string-replace.php index 0e8667dfe..905fa9a27 100644 --- a/php/class-string-replace.php +++ b/php/class-string-replace.php @@ -298,10 +298,13 @@ public function replace_strings( $content, $context = 'view' ) { if ( ! empty( $this->context ) ) { $context = $this->context; } + $is_json = false; if ( Utils::looks_like_json( $content ) ) { - $json_maybe = json_decode( $content, true ); - if ( ! empty( $json_maybe ) ) { + // Decode as objects, not associative arrays, so JSON object/array shape (e.g. empty objects `{}`) survives the round trip below. + $json_maybe = json_decode( $content ); + if ( null !== $json_maybe ) { $content = $json_maybe; + $is_json = true; } } $this->prime_replacements( $content, $context ); @@ -309,7 +312,7 @@ public function replace_strings( $content, $context = 'view' ) { $content = self::do_replace( $content ); } self::reset(); - $last_content = ! empty( $json_maybe ) ? wp_json_encode( $content ) : $content; + $last_content = $is_json ? wp_json_encode( $content ) : $content; return $last_content; }