当前位置: 首页 > 面试题库 >

无需一次将所有对象都存储在内存中的MarshalJSON

燕刚毅
2023-03-14
问题内容

我想用来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包中内置了此功能,但事实并非如此。

操场

// error: json: unsupported type: chan string
if err := json.NewEncoder(os.Stdout).Encode(&t); err != nil {
    log.Fatal(err)
}

我目前只是在自己构建json字符串。

操场

w := os.Stdout
w.WriteString(`{ "Foo": "` + t.Foo + `", "Bar": [`)

for x := range t.Bar {
    _ = json.NewEncoder(w).Encode(x)
    w.WriteString(`,`)
}

w.WriteString(`]}`)

有一个更好的方法吗?

如果json.Marshaler像这样,那将是微不足道的。

type Marshaler interface {
    MarshalJSON(io.Writer) error
}

问题答案:

不幸的是,该encoding/json程序包还没有办法做到这一点。您现在(手动)执行的操作是执行此操作的最佳方法,而无需修改内置程序包。

如果要打补丁encoding/json,则可以reflectValueQuoted在encoding
/ json /
encode.go中

修改功能

您可能需要关注Array的情况(Slice有一个fallthrough):

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

我对中的频道没有做太多事情reflect,因此上述内容可能需要其他检查。

如果您确实选择了此方法,则可以随时提交补丁。



 类似资料:
  • 问题内容: 我只是想知道我实际上可以 将对象存储在$ _SESSION中 ,因此觉得很酷,因为当我跳到另一页时,我仍然有我的对象。现在,在我开始使用这种方法之前,我想了解一下这是否真的是一个好主意,或者是否存在 潜在的陷阱 。 我知道,如果我只有一个入口点,就不需要这样做,但是我还没有,所以我没有一个入口点,我真的很想保留我的对象,因为我没有那样不会失去我的状态。(现在,我还读过我应该对无状态站点

  • 问题内容: 这就是事情- 我想在特定键下的redis中存储本机JS(node.js)对象(闪存套接字引用)。当我简单地做到这一点时,它存储为一个字符串。当我尝试获得价值时,我得到的只是一个字符串。 有机会工作吗?这是我的代码: 问题答案: 下载者:这里的上下文是SET命令,可以存储任意对象。 不,你不能那样做。您应该接受以下事实:Redis将所有内容存储为字符串(毕竟,协议是基于文本的)。Redi

  • 问题内容: 我正在使用Java JDBC应用程序从数据库中获取约500,000条记录。使用的数据库是Oracle。取出每一行后,我立即将数据写入文件。由于完成整个数据的获取大约需要一个小时,因此我试图增加结果集的获取大小。我已经在多个链接中看到,在增加访存大小的同时,应该注意内存消耗。增加获取大小实际上是否会增加jvm使用的堆内存? 假设获取大小为10,并且程序查询总共返回100行。在第一次读取期

  • 从存储这些对象的性能和内存角度来看,哪种方法更好?单独的哈希映射或与所有这些哈希映射的列表。 我可以认为,将其存储为单独的哈希映射的一个优点是,我们不需要迭代列表来查找值是否存在。

  • 问题内容: 当编译我们的项目,我们创建几个档案(静态库),说和每个包含定义函数的对象文件和。然后,将这些归档文件合并到一个共享对象中,例如,这是我们的主要可分发目标之一。 例如,在示例程序中使用此共享库时,链接失败,因为未定义对函数和的引用。 但是,当我直接将最终的可执行文件与归档文件(静态库)链接时,它可以工作。 我的猜测是,归档中包含的目标文件未 链接 到共享库中,因为它们没有在共享库中使用。