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

如何为bufio.Scanner编写自定义splitFunc以扫描JSON对象

使用bufio.Scanner按完整JSON对象分割输入

我需要用bufio.Scanner从输入中每次读取一个完整的JSON对象,输入中可能同时包含完整和不完整的JSON结构,比如:

{
    "some_object": "name",
    "some_fileds": {}
}
{
    "some_object": 
}

只需要提取第一个完整的JSON对象,对于不完整的则等待后续输入补全后再处理。

最初我尝试自己实现splitJSON分割函数,但效果很差:

func splitJSON(
    bb []byte, atEOF bool,
) (advance int, token []byte, err error) {
    print(string(bb))
    if len(bb) < 10 {
        return 0, nil, nil
    }

    var nested, from, to int
    var end bool

    for i, b := range bb {
        if string(b) == "{" {
            if end {
                to = i

                break
            }

            if nested == 0 {
                from = i
            }

            nested++
        }

        if string(b) == "}" {
            nested--
            if nested == 0 {
                to = i
                end = true
            }
        }
    }

    if atEOF {
        return len(bb), bb, nil
    }

    return len(bb[from:to]), bb[from:to], nil
}

最终解决方案

借助标准库的json.Decoder来处理JSON的解析逻辑,实现了正确的分割函数:

func splitJSON(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }

    reader := bytes.NewReader(data)
    dec := json.NewDecoder(reader)

    var raw json.RawMessage
    if err := dec.Decode(&raw); err != nil {
        // 解析失败,说明当前数据不足以构成完整JSON,返回0等待更多输入
        return 0, nil, nil
    }

    // 前进的字节数为RawMessage的长度+1(跳过JSON对象后的换行/空格分隔符)
    return len(raw) + 1, raw, nil
}

说明

这个方法的核心是利用json.Decoder的原生解析能力,它会自动处理JSON的嵌套结构、转义字符等边界情况,比手动计数大括号的方式更可靠:

  • 当输入数据不足以解析出完整JSON时,Decode返回错误,此时分割函数返回0, nil, nil,Scanner会等待更多输入;
  • 解析成功时,json.RawMessage会保存完整的JSON字节流,同时通过Decoder的内部指针可以知道解析了多少字节,再加上分隔符的长度(+1)就是需要前进的字节数;
  • 完美处理了嵌套JSON的情况,不会因为内部的大括号导致误分割。

内容的提问来源于stack exchange,提问作者Mark Eaton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:30:56