Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go MarshalJSON,而不同时在内存中包含所有对象_Go_Marshalling - Fatal编程技术网

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(']')