如何在Go语言中解析多个独立的JSON对象?
如何在Go中解析多个独立的JSON对象
我完全懂你碰到的这个坑——用字符串替换把}{改成},{再套数组的方法看起来简单,但只要某个JSON的字符串字段里刚好出现}{(比如描述里包含类似代码片段的内容),整个解析就直接崩了,根本不靠谱。
针对你处理Common Crawl数据的场景,其实有两种更稳妥的解决方案,分情况来看:
情况1:数据是每行一个JSON对象(Common Crawl的标准输出格式)
Common Crawl的索引返回结果本来就是JSON Lines格式(每行一个完整的JSON对象),这种情况下直接用bufio.Scanner逐行读取解析就好,既高效又不会出错:
package main import ( "bufio" "encoding/json" "fmt" "strings" ) // 根据Common Crawl的输出结构定义结构体,按需添加字段 type CrawlEntry struct { URL string `json:"url"` Status string `json:"status"` Timestamp string `json:"timestamp"` } func main() { // 假设resp_body是你获取到的响应体字节数组 respBody := `{"url":"https://www.netflix.com","status":"200","timestamp":"20180426123456"} {"url":"https://help.netflix.com","status":"200","timestamp":"20180426123501"}` scanner := bufio.NewScanner(strings.NewReader(respBody)) for scanner.Scan() { line := scanner.Bytes() var entry CrawlEntry if err := json.Unmarshal(line, &entry); err != nil { fmt.Printf("解析单行JSON失败: %v\n", err) continue } // 这里处理解析后的对象 fmt.Printf("抓取URL: %s | 状态码: %s\n", entry.URL, entry.Status) } if err := scanner.Err(); err != nil { fmt.Printf("读取数据出错: %v\n", err) } }
这种方法完全不需要修改原始数据,完美适配Common Crawl的输出规范,而且内存占用也更低——不需要把整个响应体加载到内存里,逐行处理就行。
情况2:数据是无换行的连续JSON对象
如果碰到的是完全连续的JSON(比如{"something":"foo"}{"something-else":"bar"}这种没有换行的情况),可以用json.Decoder的循环解析能力,它会自动跳过JSON之间的空白字符,并且能判断是否还有后续对象:
package main import ( "encoding/json" "fmt" "strings" ) type Item struct { Something string `json:"something"` SomethingElse string `json:"something-else"` } func main() { rawData := `{"something":"foo"}{"something-else":"bar"}` decoder := json.NewDecoder(strings.NewReader(rawData)) for { var item Item err := decoder.Decode(&item) if err != nil { // 要么解析完所有对象,要么出错,直接退出循环 break } // 处理解析后的对象 if item.Something != "" { fmt.Printf("Something: %s\n", item.Something) } if item.SomethingElse != "" { fmt.Printf("Something Else: %s\n", item.SomethingElse) } // 检查是否还有未解析的JSON对象 if !decoder.More() { break } } }
这个方法彻底避免了字符串替换的风险,不管JSON里有没有嵌套的}{,json.Decoder都能正确识别每个独立的JSON边界。
总结一下:针对你的Common Crawl场景,优先用第一种逐行解析的方案,这是最贴合数据源的做法。如果碰到其他连续JSON的场景,就用第二种json.Decoder循环解析的方式。
内容的提问来源于stack exchange,提问作者Ice3man
相关产品推荐
相关产品推荐

