有两种选择。从编码的角度来看,最简单的方法就是正常解码 JSON 字符串。您可以通过解码为空结构来使其最有效:
package main
import "encoding/json"
func main() {
input := []byte(`{"a":"b", "c": 123}`)
var x struct{}
if err := json.Unmarshal(input, &x); err != nil {
panic(err)
}
input = []byte(`{"a":"b", "c": 123}xxx`) // This one fails
if err := json.Unmarshal(input, &x); err != nil {
panic(err)
}
}
(游乐场链接 https://play.golang.org/p/VheJf-cd-yD)
这种方法有一些潜在的缺点:
- 它仅适用于单个 JSON 对象。也就是说,如果没有额外的逻辑,对象列表(如问题中所要求的)将失败。
- 正如 @icza 在评论中指出的,它仅适用于 JSON 对象,因此裸数组、数字或字符串将失败。为了适应这些类型,
interface{}
必须使用,这可能会导致一些严重的性能损失。
- 扔掉的
x
仍然必须分配值,并且表下可能至少有一个反射调用,这可能会给某些工作负载带来明显的性能损失。
鉴于这些限制,我的建议是使用第二个选项:循环遍历整个 JSON 输入,忽略实际内容。使用标准库使这变得简单json.解码器 https://golang.org/pkg/encoding/json/#Decoder:
package main
import (
"bytes"
"encoding/json"
"io"
)
func main() {
input := []byte(`{"a":"b", "c": 123}`)
dec := json.NewDecoder(bytes.NewReader(input))
for {
_, err := dec.Token()
if err == io.EOF {
break // End of input, valid JSON
}
if err != nil {
panic(err) // Invalid input
}
}
input = []byte(`{"a":"b", "c": 123}xxx`) // This input fails
dec = json.NewDecoder(bytes.NewReader(input))
for {
_, err := dec.Token()
if err == io.EOF {
break // End of input, valid JSON
}
if err != nil {
panic(err) // Invalid input
}
}
}
(游乐场链接 https://play.golang.org/p/QHYK3aCEImk)