Go MarshalJSON,而不同时在内存中包含所有对象
我想使用Go MarshalJSON,而不同时在内存中包含所有对象,go,marshalling,Go,Marshalling,我想使用json.Encoder对大量数据流进行编码,而无需将所有数据一次性加载到内存中 // I want to marshal this t := struct { Foo string // Bar is a stream of objects // I don't want it all to be in memory at the same time. Bar chan string }{ Foo: "Hello World", B
json.Encoder
对大量数据流进行编码,而无需将所有数据一次性加载到内存中
// I want to marshal this
t := struct {
Foo string
// Bar is a stream of objects
// I don't want it all to be in memory at the same time.
Bar chan string
}{
Foo: "Hello World",
Bar: make(chan string),
}
// long stream of data
go func() {
for _, x := range []string{"one", "two", "three"} {
t.Bar <- x
}
close(t.Bar)
}()
我目前正在自己构建json字符串
有更好的方法吗
如果事情是这样的,那将是微不足道的
type Marshaler interface {
MarshalJSON(io.Writer) error
}
您可以在结构中的
MarshalJSON
方法中解压通道,如下所示:
type S struct {
Foo string
Bar chan string
}
func (s *S) MarshalJSON() (b []byte, err error) {
b, err := json.Marshal(s.Foo)
if err != nil { return nil, err }
for x := range s.Bar {
tmp, err := json.Marshal(x)
if err != nil { return nil, err }
b = append(b, tmp...)
}
return
}
// Inside switch:
case reflect.Chan:
e.WriteByte('[')
i := 0
for {
x, ok := v.Recv()
if !ok {
break
}
if i > 0 {
e.WriteByte(',')
}
e.reflectValue(x)
i++
}
e.WriteByte(']')
不幸的是,
encoding/json
包还没有办法做到这一点。您现在所做的(手动)是最好的方法,无需修改内置包
如果要修补encoding/json
,可以在中修改reflectValueQuoted
函数
您可能希望将重点放在阵列情况上(切片有一个故障排除)
:
我对reflect
中的频道没有做太多的处理,因此上面的内容可能需要其他检查
如果你最终选择了这条路线,你可以提交一个补丁。这种方法可以一次将所有内容加载到内存中。这正是我想要避免的。啊,抱歉,我误解了你。因为我喜欢在自定义封送处理程序实现中解压通道的纯粹想法,所以显示的代码不处理逗号。所以在Foo和第一个从Bar出来的值之间会缺少一个。你是绝对正确的。最好的方法可能是生成一个结构并进行编组,而不是追加字节。请随意建议编辑,我现在没什么时间:(@iliachory,如果你打算做那个补丁,请告诉我。听起来很有趣,如果你不打算做,我想试试。
type S struct {
Foo string
Bar chan string
}
func (s *S) MarshalJSON() (b []byte, err error) {
b, err := json.Marshal(s.Foo)
if err != nil { return nil, err }
for x := range s.Bar {
tmp, err := json.Marshal(x)
if err != nil { return nil, err }
b = append(b, tmp...)
}
return
}
// Inside switch:
case reflect.Array:
e.WriteByte('[')
n := v.Len()
for i := 0; i < n; i++ {
if i > 0 {
e.WriteByte(',')
}
e.reflectValue(v.Index(i))
}
e.WriteByte(']')
// Inside switch:
case reflect.Chan:
e.WriteByte('[')
i := 0
for {
x, ok := v.Recv()
if !ok {
break
}
if i > 0 {
e.WriteByte(',')
}
e.reflectValue(x)
i++
}
e.WriteByte(']')