You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

蓝牙接收Arduino JSON payload遇JSONDecodeError问题求助

Arduino蓝牙传输JSON到Python的解析问题及解决方法

问题背景

我正从Arduino微控制器传输JSON payload,并用Python脚本接收,脚本代码如下:

import bluetooth  #pybluez 
import json

sensor_address = "18:D9:31:YY:C7:4A"
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
socket.connect((sensor_address, 1))
buffer = ""

print("Listening...")
while True: 
    data = socket.recv(1024)
    buffer += str(data, encoding='ascii')
    print(buffer) # used to check json payload
    try: 
        data = json.loads(buffer)
        print("Received:", data)
        buffer = ""
    except json.JSONDecodeError as e:
        print(e)
        continue

接收时,try语句执行前的buffer内容为连续拼接的JSON对象:

{"a_x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-2.816794,"g_y":2.572519}{"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g_x":-1,"g_y":0.374046}

但脚本反复输出Expecting value: line 1 column 1 (char 0)错误,try块内代码始终无法执行。疑问:为何完整payload接收后代码仍不执行?能否用正则表达式从字符串中提取有效payload?

错误原因

  • 连续拼接的JSON不是合法格式:json.loads()只能解析单个JSON值(对象、数组等),而你收到的是多个JSON对象直接拼接(无逗号分隔,也没有外层数组包裹),整个buffer内容属于非法JSON,必然解码失败。
  • 流式读取的不确定性:蓝牙串口的recv()是流式读取,每次收到的可能是部分JSON片段,或者多个完整JSON+部分片段的混合,导致buffer内容始终无法被json.loads()正常解析。

解决方案

方法1:修改Arduino输出格式(最优方案)

直接在Arduino发送JSON时,给每个JSON对象添加分隔符,让Python端可以轻松分割:

  • 方案A:每个JSON对象末尾添加换行符\n,Python端按行分割处理,每次读取一行完整的JSON。
  • 方案B:将多个JSON对象包裹成一个JSON数组发送(如[{"a_x":...}, {"a_x":...}]),但需注意批量发送或实时处理的节奏控制。

方法2:Python端用正则提取完整JSON对象

如果无法修改Arduino代码,可通过正则表达式从buffer中匹配所有完整的JSON对象,处理后移除已解析的部分,保留剩余的不完整片段等待后续拼接。

修改后的Python脚本示例:

import bluetooth  # pybluez 
import json
import re

sensor_address = "18:D9:31:YY:C7:4A"
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
socket.connect((sensor_address, 1))
buffer = ""

# 匹配无嵌套的完整JSON对象的正则
json_obj_pattern = re.compile(r'\{[^{}]*\}')

print("Listening...")
while True: 
    data = socket.recv(1024)
    buffer += str(data, encoding='ascii')
    
    # 提取所有完整的JSON对象
    matches = json_obj_pattern.findall(buffer)
    if matches:
        for match in matches:
            try:
                parsed_data = json.loads(match)
                print("Received:", parsed_data)
            except json.JSONDecodeError as e:
                print(f"解析单个JSON失败: {e}")
        # 移除已处理的完整JSON,保留剩余的不完整片段
        buffer = buffer[len(''.join(matches)):]

正则说明

\{[^{}]*\}:匹配以{开头、}结尾,中间不含{}的字符串,适用于无嵌套结构的JSON对象(你的数据刚好符合该场景)。如果涉及嵌套JSON,建议使用专门的流式JSON解析库(如ijson)来处理更复杂的情况。

内容的提问来源于stack exchange,提问作者John Harrington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:42:49