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

无显式分隔符时如何正确拆分Socket缓冲JSON日志数据

处理无分隔符嵌套JSON日志的Socket接收方案

我通过Socket接收由无固定长度、无显式分隔符的JSON日志组成的数据,部分日志存在嵌套JSON结构,无法直接用}作为分隔符拆分。此前采用Python的partition()方法,以b"'}"作为分隔符从缓冲中提取完整JSON对象,该方法仅在日志最后字段为字符串时有效,当最后字段为整数时无法正确拆分,求可行解决方案。

现有Buffer类代码:

class Buffer:

    def __init__(self,sock):
        self.sock = sock
        self.buffer = b''

    def get_line(self):
        while b"'}" not in self.buffer:
            log_b = self.sock.recv(8192)
            if not log_b:
                return None
            self.buffer += log_b

        log_p, sep, self.buffer = self.buffer.partition(b"'}")
        log_p = log_p + sep
        return log_p

解决方案

核心思路是利用JSON解析器的增量解析能力,通过识别完整的JSON语法结构来拆分日志,而非依赖固定分隔符。这种方法能自动处理嵌套大括号、不同类型结尾的日志,彻底解决拆分异常问题。

改进后的Buffer类实现

由于日志采用Python字典风格的单引号格式(非标准JSON),我们先将其转换为标准JSON格式,再使用json.JSONDecoder.raw_decode()方法实现增量解析——该方法会返回第一个完整JSON对象的结束位置,据此可准确拆分缓冲数据:

import json

class Buffer:
    def __init__(self, sock):
        self.sock = sock
        self.buffer = b''
        self.decoder = json.JSONDecoder()

    def get_line(self):
        while True:
            try:
                # 将缓冲字节转为字符串
                data_str = self.buffer.decode('utf-8')
                # 转换为标准JSON格式(替换单引号为双引号)
                json_compatible_str = data_str.replace("'", '"')
                # 增量解析第一个完整JSON对象,获取结束位置
                _, end_pos = self.decoder.raw_decode(json_compatible_str)
                # 提取完整日志的字节数据
                full_log = self.buffer[:end_pos]
                # 更新缓冲,保留未解析的剩余数据
                self.buffer = self.buffer[end_pos:]
                return full_log
            except (json.JSONDecodeError, UnicodeDecodeError):
                # 缓冲数据不完整,继续接收
                chunk = self.sock.recv(8192)
                if not chunk:
                    # 连接关闭,返回None
                    return None
                self.buffer += chunk

方案优势

  • 兼容嵌套结构:解析器会识别JSON的层级结构,不会误将嵌套的}当作日志结束符
  • 适配任意结尾类型:无论日志最后字段是字符串、整数还是其他JSON类型,都能准确识别完整对象
  • 鲁棒性强:通过增量解析逐步缓冲数据,确保不会遗漏或截断日志

特殊情况处理

如果日志字符串内部包含单引号(如'It\'s a test'),直接替换单引号会破坏字符串结构,此时可改用正则表达式仅替换字符串外部的单引号:

import re

def convert_to_json(s):
    # 匹配不在转义单引号和成对单引号内的单引号
    return re.sub(r"(?<!\\)'(?!(([^']*'){2})*[^']*$)", '"', s)

将上述函数替换原代码中的data_str.replace("'", '"')即可。

内容的提问来源于stack exchange,提问作者m.yagmur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 05:54:09