Java通过Socket发送JSON至Python服务端,json.loads解析失败求助
Java Socket发送JSON到Python服务端,json.loads解码失败
Java端构造JSONObject后通过Socket发送,Python服务端能接收数据,但调用json.loads()时抛出JSONDecodeError,无法转换为字典处理。
Java代码
JSONObject obj = new JSONObject(); Socket clientSocket; [...] clientSocket = new Socket(Server.getOrchestrator(), 5051); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); obj.put("operation", "provider list"); outToServer.writeUTF(obj.toString());
Python代码
socket = (socket configuration here) socket.listen(5) client, address = socket.accept() threading.Thread(target=self.serve_client, args=(client, address)).start()
def serve_client(self, client, address): SIZE = 1024 while True: recv_data = client.recv(SIZE).decode('utf-8') print(recv_data) print(type(recv_data)) recv_data = json.loads(recv_data) # <-- 此处报错
报错信息
error JSONDecodeError('Expecting value: line 1 column 1 (char 0)',)
解码前的接收数据
b'\x00\x1d{"operation":"provider list"}'
尝试过的解决方法
Java端尝试
替换DataOutputStream为以下方式,但程序挂起,Python无接收内容:
OutputStreamWriter outToServer = new OutputStreamWriter (clientSocket.getOutputStream(), StandardCharsets.UTF_8);
BufferedReader outToServer = new BufferedReader(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8));
Python端尝试
尝试1:
recv_data = client.recv(SIZE) # 未解码,为字节类型 recv_data = json.dumps(recv_data) # 因无法处理字节报错 recv_data = json.loads(recv_data)
尝试2:
recv_data = client.recv(SIZE).decode('utf-8') recv_data = json.dumps(recv_data) # 执行成功 print(f"String recv_data converted in string: {recv_data}\nRecv_data type {type(recv_data)}) recv_data = json.loads(recv_data) # 未返回字典,仍为字符串 print(f"String recv_data converted in dictionary: {recv_data}\nRecv_data type {type(recv_data)})
尝试2的输出:
{"operation":"provider list"} <class 'str'> String recv_data converted in string: "\u0000\u001d{\"operation\":\"provider list\"}" Recv_data tyoe: <class 'str'> String recv_data converted in a dictionary: {"operation": "provider list"} Recv_data type: <class 'str'>
问题根源
DataOutputStream.writeUTF()会在字符串前添加2字节的UTF-8长度前缀(你收到的b'\x00\x1d'就是这个前缀,0x1d对应29,是后面JSON字符串的长度),Python的recv()会把这个前缀一起读入,导致JSON解析器无法识别有效JSON起始位置,抛出错误。
解决方案
方案1:修改Java发送逻辑(推荐)
放弃DataOutputStream.writeUTF(),直接用OutputStreamWriter发送UTF-8编码的JSON字符串,避免自动添加长度前缀,同时必须调用flush()确保数据发送:
JSONObject obj = new JSONObject(); Socket clientSocket = new Socket(Server.getOrchestrator(), 5051); // 直接用UTF-8编码的输出流发送 OutputStreamWriter outToServer = new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8); obj.put("operation", "provider list"); outToServer.write(obj.toString()); outToServer.flush(); // 关键:强制将缓冲区数据发送出去 // 按需关闭资源 // outToServer.close(); // clientSocket.close();
方案2:Python端兼容长度前缀
如果无法修改Java代码,Python端需要先读取前2字节的长度前缀,再读取对应长度的JSON数据:
def serve_client(self, client, address): while True: # 先读取2字节的长度前缀 len_prefix = client.recv(2) if not len_prefix: break # 连接断开 # 将2字节前缀转为整数(大端字节序,对应Java writeUTF的格式) data_length = int.from_bytes(len_prefix, byteorder='big') # 读取指定长度的JSON数据(若数据量大需循环读取) recv_data = b'' while len(recv_data) < data_length: chunk = client.recv(data_length - len(recv_data)) if not chunk: break recv_data += chunk # 解码并解析JSON json_data = json.loads(recv_data.decode('utf-8')) print(json_data, type(json_data))
内容的提问来源于stack exchange,提问作者Phoenix
相关产品推荐
相关产品推荐

