开发者社区> 问答> 正文

MySQL5.7 JSON解析问题

canal 版本1.0.24 写入MySQL的JSON数据,Canal解析失败

2017-06-22 11:39:25.104 [destination = example , address = /127.0.0.1:3306 , EventParser] ERROR com.alibaba.otter.canal.common.alarm.LogAlarmHandler - destination:example[com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed. Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed. Caused by: java.lang.IllegalArgumentException: illegal json data at com.taobao.tddl.dbsync.binlog.JsonConversion.parse_array_or_object(JsonConversion.java:81) at com.taobao.tddl.dbsync.binlog.JsonConversion.parse_value(JsonConversion.java:61) at com.taobao.tddl.dbsync.binlog.event.RowsLogBuffer.fetchValue(RowsLogBuffer.java:955) at com.taobao.tddl.dbsync.binlog.event.RowsLogBuffer.nextValue(RowsLogBuffer.java:99) at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseOneRow(LogEventConvert.java:495) at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEvent(LogEventConvert.java:376) at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parse(LogEventConvert.java:108) at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parse(LogEventConvert.java:62) at com.alibaba.otter.canal.parse.inbound.AbstractEventParser.parseAndProfilingIfNecessary(AbstractEventParser.java:326) at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3$1.sink(AbstractEventParser.java:176) at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.dump(MysqlConnection.java:130) at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3.run(AbstractEventParser.java:209) at java.lang.Thread.run(Thread.java:745)

另外如果json中包含双引号,canal解析之后丢失了转义符号。

提问368.png

两个问题,第一个问题还没找到出问题的SQL, 第二个是canal已经解析了,并且canal client可以拿到数据。

+-------+-------------+------+-----+-------------------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+-------------------+-------+ | id | int(11) | NO | PRI | NULL | | | dt | timestamp | NO | | CURRENT_TIMESTAMP | | | json1 | json | YES | | NULL | | | aa | varchar(50) | YES | | NULL | | +-------+-------------+------+-----+-------------------+-------+

insert into t1(id, json1, aa) values(3,"{"test":"aa\"aa"}", "a");

查回来是这样的 +----+---------------------+--------------------+------+ | id | dt | json1 | aa | +----+---------------------+--------------------+------+ | 3 | 2017-06-22 14:34:19 | {"test": "aa"aa"} | a | +----+---------------------+--------------------+------+ canal client取出的json如图。 变成了{"test":"aa"aa"}。

原提问者GitHub用户toruneko

展开
收起
绿子直子 2023-05-09 15:13:55 117 0
2 条回答
写回答
取消 提交回答
  • 首先需要确认一下MySQL5.7的JSON解析器是否支持该JSON格式,可以使用以下命令检查:

    SELECT JSON_UNQUOTE(json_data) FROM table WHERE id = 1;

    如果返回的结果与原JSON格式一致,则说明解析器能够正常解析JSON数据。如果返回的结果与原JSON格式不同,则需要升级MySQL5.7的JSON解析器或者使用其他方式处理JSON数据。

    Canal解析JSON数据时会自动将双引号进行转义,如果在MySQL中存储的数据包含双引号,则可能导致解析后的数据丢失双引号。可以考虑在写入MySQL数据时使用REPLACE函数将双引号替换为反斜杠(),例如:

    INSERT INTO table (id, json1, aa) VALUES (3, replace(json_data, '"', '\'), 'a');

    另外,建议在查询MySQL数据前先对数据进行编码和解码,避免出现乱码问题。例如:

    SELECT CONCAT(CAST(json_data AS CHAR), '{}') AS decoded_data FROM table WHERE id = 1;

    2023-05-23 16:07:21
    赞同 展开评论 打赏
  • 找到导致illegal json data 的SQL了。 json大概有25000个字节,就补贴出来了。

    会不会是因为json太大,导致bytes和len长度计算错误。

    原回答者GitHub用户toruneko

    2023-05-10 10:35:33
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
One Box: 解读事务与分析一体化数据库 HybridDB for MySQL 立即下载
One Box:解读事务与分析一体化数据库HybridDB for MySQL 立即下载
如何支撑HTAP场景-HybridDB for MySQL系统架构和技术演进 立即下载

相关镜像