From c341aa0014c7a1b852ebe10f55a6c10ca7e5e8a3 Mon Sep 17 00:00:00 2001 From: Sharang Gupta Date: Wed, 28 Oct 2026 23:59:59 +0000 Subject: [PATCH] Encode JSON parameters in the connection charset Since #1685 JSON parameters were always written as UTF-8, so a connection with a non-UTF-8 collation received garbled text. Signed-off-by: Sharang Gupta Assisted-by: Anthropic Claude (claude-opus-5-5) --- .../mysqlclient/impl/datatype/DataTypeCodec.java | 9 +++++++-- .../tests/mysqlclient/MySQLCollationTest.java | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/vertx-mysql-client/src/main/java/io/vertx/mysqlclient/impl/datatype/DataTypeCodec.java b/vertx-mysql-client/src/main/java/io/vertx/mysqlclient/impl/datatype/DataTypeCodec.java index d153e4cd57..c75914cefe 100644 --- a/vertx-mysql-client/src/main/java/io/vertx/mysqlclient/impl/datatype/DataTypeCodec.java +++ b/vertx-mysql-client/src/main/java/io/vertx/mysqlclient/impl/datatype/DataTypeCodec.java @@ -30,6 +30,7 @@ import java.math.BigInteger; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; @@ -179,7 +180,7 @@ public static void encodeBinary(DataType dataType, Object value, Charset charset case VARSTRING: default: if (value instanceof JsonObject || value instanceof JsonArray) { - binaryEncodeJson(value, buffer); + binaryEncodeJson(value, buffer, charset); return; } else if (value == Tuple.JSON_NULL) { // we have to make JSON literal null send as a STRING data type @@ -467,7 +468,11 @@ private static void binaryEncodeDatetime(LocalDateTime value, ByteBuf buffer) { } } - private static void binaryEncodeJson(Object value, ByteBuf buffer) { + private static void binaryEncodeJson(Object value, ByteBuf buffer, Charset charset) { + if (!StandardCharsets.UTF_8.equals(charset)) { + BufferUtils.writeLengthEncodedString(buffer, Json.encode(value), charset); + return; + } ByteBuf tmp = buffer.alloc().buffer(); try { Json.encodeTo(value, new ByteBufOutputStream(tmp)); diff --git a/vertx-mysql-client/src/test/java/io/vertx/tests/mysqlclient/MySQLCollationTest.java b/vertx-mysql-client/src/test/java/io/vertx/tests/mysqlclient/MySQLCollationTest.java index 45482ed398..9390b467e4 100644 --- a/vertx-mysql-client/src/test/java/io/vertx/tests/mysqlclient/MySQLCollationTest.java +++ b/vertx-mysql-client/src/test/java/io/vertx/tests/mysqlclient/MySQLCollationTest.java @@ -12,6 +12,7 @@ package io.vertx.tests.mysqlclient; import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; import io.vertx.mysqlclient.MySQLConnectOptions; @@ -95,6 +96,20 @@ public void testConnectionCharset(TestContext ctx) { })); } + @Test + public void testJsonParameterWithConnectionCollation(TestContext ctx) { + MySQLConnectOptions connectOptions = options.setCollation("gbk_chinese_ci"); + MySQLConnection.connect(vertx, connectOptions).onComplete(ctx.asyncAssertSuccess(conn -> { + conn + .preparedQuery("SELECT JSON_UNQUOTE(JSON_EXTRACT(CAST(? AS JSON), '$.city')) AS city") + .execute(Tuple.of(new JsonObject().put("city", "\u5317\u4EAC"))) + .onComplete(ctx.asyncAssertSuccess(res -> { + ctx.assertEquals("\u5317\u4EAC", res.iterator().next().getString("city")); + conn.close(); + })); + })); + } + @Test public void testTableCollationBinary(TestContext ctx) { testBinary(ctx, PREPARE_TESTING_TABLE_DATA);