json - 如何为扫描 json 对象的 bufio.Scaner 编写自定义 splitFunc

标签 json go

我有这样的代码

scanner := bufio.NewScanner(reader)
scanner.Split(splitJSON)

for scanner.Scan() {
    bb := scanner.Bytes()
}

我想一次只从 Scanner 获取一个有效的 JSON 对象。在某些情况下,在 Scanner 中可能是这样表示结构的字节

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

我只需要这个的第一部分

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

对于另一个,我应该等待 JSON 对象的结束。

我有一个这样的函数,但它太糟糕了而且不起作用。

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
}

更新 由这个splitFunc决定

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 {
        return 0, nil, nil
    }

    return len(raw) + 1, raw, nil
}

最佳答案

使用json.Decoder为了这。每个Decoder.Decode()调用将从您的案例中的输入 JSON 对象解码下一个 JSON 编码值。

如果您不想解码只需要 JSON 数据(字节 slice )的 JSON 对象,请使用 json.RawMessage解编成。

例如:

func main() {
    reader := strings.NewReader(src)
    dec := json.NewDecoder(reader)

    for {
        var raw json.RawMessage
        if err := dec.Decode(&raw); err != nil {
            if err == io.EOF {
                break
            }
            fmt.Printf("Error:", err)
            return
        }
        fmt.Println("Next:", string(raw))
    }
}

const src = `{
    "some_object": "name",
    "some_fileds": {}
}
{
    "some_object": "foo"
}`

这将输出(在 Go Playground 上尝试):

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

关于json - 如何为扫描 json 对象的 bufio.Scaner 编写自定义 splitFunc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73786151/

相关文章:

go - 无效操作 : currency. Name() == 货币(类型字符串和 *config.Currency 不匹配)

python - 如何自动修复无效的 JSON 字符串?

ruby-on-rails - 在 Rails 中查询 Postgres JSON 数组字段

php - 将数组值转换为 longtoip

json - 检查字符串是否为 JSON 格式

go lang version-able 字符串规范化

ios - 来自 JSON 的 SwiftUI Picker 数据未显示

python - Django - Haystack 查询序列化

performance - 是否可以内联函数,在 Golang 中包含循环?

multithreading - 我的 Go 程序如何让所有 CPU 内核保持忙碌状态?