我有一个包含单个字段的 JSON 文件,当加载到内存中时,该文件占用巨大 的空间。其他字段是合理的,但我尽量注意不要加载该特定字段,除非我绝对必须这样做。
{
"Field1": "value1",
"Field2": "value2",
"Field3": "a very very long string that potentially takes a few GB of memory"
}
将该文件读入内存时,我想忽略 Field3
(因为加载它可能会使我的应用程序崩溃)。这里有一些代码,我认为这样做是因为它使用 io 流,而不是将 []byte
类型传递给 Unmarshal
命令。
package main
import (
"encoding/json"
"os"
)
func main() {
type MyStruct struct {
Field1 string
Field2 string
}
fi, err := os.Open("myJSONFile.json")
if err != nil {
os.Exit(2)
}
// create an instance and populate
var mystruct MyStruct
err = json.NewDecoder(fi).Decode(&mystruct)
if err != nil {
os.Exit(2)
}
// do some other stuff
}
问题是内置的 json.Decoder
类型在丢弃与 struct
的字段(正如之前在 StackOverflow 上指出的那样:link)。
有没有什么方法可以在不将整个 JSON 对象保存在内存中的情况下在 Go 中解码 JSON?
最佳答案
您可以编写一个自定义的 io.Reader
并将其提供给 json.Decoder
,这将预读您的 json 文件并跳过该特定字段。
另一种选择是编写自己的解码器,更加复杂和困惑。
//edit 这似乎是一个有趣的练习,所以这里是:
type IgnoreField struct {
io.Reader
Field string
buf bytes.Buffer
}
func NewIgnoreField(r io.Reader, field string) *IgnoreField {
return &IgnoreField{
Reader: r,
Field: field,
}
}
func (iF *IgnoreField) Read(p []byte) (n int, err error) {
if n, err = iF.Reader.Read(p); err != nil {
return
}
s := string(p)
fl := `"` + iF.Field + `"`
if i := strings.Index(s, fl); i != -1 {
l := strings.LastIndex(s[0:i], ",")
if l == -1 {
l = i
}
iF.buf.WriteString(s[0:l])
s = s[i+1+len(fl):]
i = strings.Index(s, `"`)
if i != -1 {
s = s[i+1:]
}
for {
i = strings.Index(s, `"`) //end quote
if i != -1 {
s = s[i+1:]
fmt.Println("Skipped")
break
} else {
if n, err = iF.Reader.Read(p); err != nil {
return
}
s = string(p)
}
}
iF.buf.WriteString(s)
}
ln := iF.buf.Len()
if ln >= len(p) {
tmp := iF.buf.Bytes()
iF.buf.Reset()
copy(p, tmp[0:len(p)])
iF.buf.Write(p[len(p):])
ln = len(p)
} else {
copy(p, iF.buf.Bytes())
iF.buf.Reset()
}
return ln, nil
}
func main() {
type MyStruct struct {
Field1 string
Field2 string
}
fi, err := os.Open("myJSONFile.json")
if err != nil {
os.Exit(2)
}
// create an instance and populate
var mystruct MyStruct
err := json.NewDecoder(NewIgnoreField(fi, "Field3")).Decode(&mystruct)
if err != nil {
fmt.Println(err)
}
fmt.Println(mystruct)
}
关于json - 不要将不需要的 JSON 键值读入内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25002575/