调用json.loads解析MQTT消息时报JSONDecodeError: Extra data错误如何解决?
问题原因
- 报错
JSONDecodeError: Extra data的核心是待解析的字符串中,除了合法JSON内容外还存在多余字符。你单独复制打印的载荷可以正常解析,是因为logger输出时会自动过滤不可见字符,实际m_decode变量中包含打印不可见的冗余内容,最常见的是MQTT载荷末尾的空字节(\0)、换行符、回车符等控制字符,部分设备端发送MQTT消息时会主动添加这类结束标识,或者传输过程中出现了字符冗余。 - 少数情况是单条MQTT消息中拼接了多条JSON报文,多个JSON对象连在一起也会触发该报错。
排查方法
在解码后先打印字符串的原始转义形式,确认是否存在冗余字符:
def on_message_mqtt(self, client, userdata, message): m_decode = message.payload.decode('utf-8') logger.info(repr(m_decode)) # 会把不可见字符转义为\x00、\n这类可见形式 # 后续逻辑
解决方案
方案1:清洗首尾冗余字符(90%以上场景可用)
直接对解码后的字符串执行首尾去空白/控制符操作,默认会清除空字节、换行、回车、空格等冗余内容:
def on_message_mqtt(self, client, userdata, message): m_decode = message.payload.decode('utf-8').strip() logger.info(m_decode) m_in = json.loads(m_decode) logger.info(m_in)
方案2:提取合法JSON区间
如果冗余字符出现在JSON内容的前后位置,可以直接截取第一个{到最后一个}之间的内容解析:
def on_message_mqtt(self, client, userdata, message): m_decode = message.payload.decode('utf-8') start_idx = m_decode.find('{') end_idx = m_decode.rfind('}') if start_idx == -1 or end_idx == -1: logger.warning("收到的消息不包含合法JSON结构") return json_str = m_decode[start_idx: end_idx+1] m_in = json.loads(json_str) logger.info(m_in)
方案3:处理单条消息多条JSON的场景
如果确认是单条MQTT消息中拼接了多条JSON报文,可以用JSONDecoder的raw_decode方法逐段解析:
import json def on_message_mqtt(self, client, userdata, message): m_decode = message.payload.decode('utf-8').strip() decoder = json.JSONDecoder() pos = 0 while pos < len(m_decode): try: m_in, pos = decoder.raw_decode(m_decode, pos) logger.info(m_in) # 处理每条解析出来的JSON对象 except json.JSONDecodeError as e: logger.error(f"解析失败,剩余内容: {m_decode[pos:]},错误: {e}") break
内容的提问来源于stack exchange,提问作者Ashen
相关产品推荐
相关产品推荐

