如何修复 MySql 的 JSON 和 Java 的编码问题?

Joh*_*ode 5 java mysql eclipse encoding

老问题,当从 MySql 数据库返回查询时,我得到像 ç 而不是 ç 的字符。

我正在使用一个非常简单的类来尝试解决问题:

package com.dataTest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class EncodingTest {

    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");

        Connection connection = DriverManager
                .getConnection("jdbc:mysql://internalip:3306/databasename?" + 
                               "user=user" +
                               "&password=password" + 
                               "&characterEncoding=utf-8" + 
                               "&useUnicode=yes");

        PreparedStatement stmt =
                connection.prepareStatement("SELECT * FROM `databasename`.teste_json;");
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            System.out.println(rs.getString("info"));
        }

        rs.close();
        stmt.close();
        connection.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

该信息是通过其他类添加到数据库中的,但我使用工作台手动更改了它,问题仍然存在。

数据库排序规则为 utf8_general_ci,表编码为 utf8。

我真的不知道该怎么办。

编辑:

我将 JSON 字符串复制到 varchar(1500) 字段,它打印完美。忘了说了,查询(info)中提到的字段是一个JSON字段。

EDIT2:这不是mojibake?

问题已根据 Rick James 的回答而关闭,声称它是 Mojibake。

根据问题Trouble with utf8 characters; 我看到的不是我存储的以下观察结果:

  • 要存储的字节需要采用 UTF-8 编码。解决这个问题。

我认为它们存储正确。我为 HEX、LENGTH 和 CHAR_LENGTH 制作了一个简单的 JSON,如下所示:

'[{\"é\": \"\"}]', '5B7B22C3A9223A2022227D5D', '12', '11'
Run Code Online (Sandbox Code Playgroud)
  • INSERTing和SELECTing text时的连接需要指定utf8或utf8mb4。解决这个问题。

连接字符串指定字符集:

&useUnicode=yes&characterEncoding=UTF-8
Run Code Online (Sandbox Code Playgroud)
  • 该列需要声明为 CHARACTER SET utf8(或 utf8mb4)。解决这个问题。

好吧,数据库有 charset/collat​​ion = utf8/utf8_general_ci 表有 collat​​ion utf8_unicode_ci JSON 列(这是有问题的那一列)没有 collat​​ion。

多么奇怪。

手册指出

MySQL 使用 utf8mb4 字符集和 utf8mb4_bin 排序规则处理 JSON 上下文中使用的字符串。其他字符集中的字符串根据需要转换为 utf8mb4。(对于 ascii 或 utf8 字符集中的字符串,不需要转换,因为 ascii 和 utf8 是 utf8mb4 的子集。)

来自https://dev.mysql.com/doc/refman/5.7/en/json.html

这是否意味着实际的排序规则已经正确?

据我了解,服务器中插入的信息是正确的(见HEX信息)所以问题是选择?但是连接字符串似乎在所有形式中都是正确的。

编辑:不是重复的。

这种情况下的问题与另一个问题中的问题不同,请参阅我自己对此问题的回答和提到的错误报告。

Joh*_*ode 6

TLDR:使用以下 utf8mb4、utf16 或 utf32 之一进行转换。

正如用户 pvg 所评论的,MySql 似乎将他们的 JSON 格式存储在 utf8 字符类型(utf8mb4、utf8、ascii)中,至少他们的文档是这样说的。根据此错误报告(https://bugs.mysql.com/bug.php?id=81677),JSON存储在 utf8mb4 中,但当前 JDBC 驱动程序不支持该编码(如 2017 年 4 月,这是工件 mysql-connector-java,版本 6.0.6)。

有趣的是,MySql 有一个CONVERT()函数可以这样使用CONVERT(info USING utf8)

更改我的查询以SELECT field1, field2, CONVERT(info USING utf8) as info FROM databasename.teste_json;完全解决我的问题。

以下是 MySql 中不同编码类型的一些结果。

我更改了更复杂的字段名称,只是为了检查会发生什么。我使用的字符串是 ãõêçé?????????

在 Java 程序中,我删除了连接字符串中的所有编码引用,这些是使用CONVERT在 MySql 文档中找到的几种编码的结果(https://dev.mysql.com/doc/refman/5.5/en/charset-charsets.html ):

big5     {"name": "???????????????"}
dec8     {"name": "?ãõêçé?????????"}
cp850    {"name": "?ãõêçé?????????"}
hp8      {"name": "?âêÁµÅ?????????"}
koi8r    {"name": "???????????????"}
latin1   {"name": "?ãõêçé?????????"}
latin2   {"name": "????çé?????????"}
swe7     {"name": "?????`?????????"}
ascii    {"name": "???????????????"}
ujis     {"name": "?ãõêçé?????????"}
sjis     {"name": "???????????????"}
hebrew   {"name": "???????????????"}
tis620   {"name": "???????????????"}
euckr    {"name": "???????????????"}
koi8u    {"name": "???????????????"}
gb2312   {"name": "???ê?é?????????"}
greek    {"name": "???????????????"}
cp1250   {"name": "????çé?????????"}
gbk      {"name": "???ê?é?????????"}
latin5   {"name": "?ãõêçé?????????"}
armscii8 {"name": "???????????????"}
utf8     {"name": "?ãõêçé?????????"}
ucs2     {"name": "?ãõêçé?????????"}
cp866    {"name": "???????????????"}
keybcs2  {"name": "?????é?????????"}
macce    {"name": "??õ??é?????????"}
macroman {"name": "?ãõêçé?????????"}
cp852    {"name": "????çé?????????"}
latin7   {"name": "??õ??é?????????"}
utf8mb4  {"name": "ãõêçé?????????"}
cp1251   {"name": "???????????????"}
utf16    {"name": "ãõêçé?????????"}
cp1256   {"name": "???êçé?????????"}
cp1257   {"name": "??õ??é?????????"}
utf32    {"name": "ãõêçé?????????"}
binary   {"name": "ðÃ£ÃµÃªÃ§Ã©æ¥æ¬èªã®ã­ã¼ãã¼ã"}
geostd8  {"name": "???????????????"}
cp932    {"name": "???????????????"}
eucjpms  {"name": "?ãõêçé?????????"}
Run Code Online (Sandbox Code Playgroud)

请注意,能够正确显示所有字符(包括笑脸)的唯一编码是 utf8mb4、utf16、utf32。

编辑:从另一篇文章中的所有讨论来看,这似乎是 JDBC 驱动程序中的某种错误,至少一切都指向它,目前可能的解决方法是使用 utf8mb4 强制转换。如果您想了解更多有关编码问题的信息,我强烈建议您通读 Rick James 的相关资料。