猿问

如何连续附加到 Go 中的 JSON 文件?

我想知道如何在 Go 中连续写入同一个文件?我必须使用os.WriteAt()吗?


JSON 基本上只是一个充满结构的数组:


[

    {

        "Id": "2817293",

        "Data": "XXXXXXX"

    },

    {

        "Id": "2817438",

        "Data": "XXXXXXX"

    }

    ...

]

我想要连续向它添加正确的数据,即在关闭文件之前多次附加到该 JSON 数组。我要写入文件的数据是所述结构的一部分:


dataToWrite := []struct{

    Id   string

    Data string

}{}

在 Go 中连续写入 JSON 数组的正确方法是什么?


我当前的方法在 JSON 文件中创建多个切片,因此不是我想要的。写入过程(位于 for 循环中)如下所示:


...

            // Read current state of file

            data := []byte{}

            f.Read(data)


            // Write current state to slice

            curr := []Result{}

            json.Unmarshal(data, &curr)


            // Append data to the created slice

            curr = append(curr, *initArr...)

            JSON, _ := JSONMarshal(curr)


            // Empty data container

            initArr = &[]Result{}


            // Write

            _, err := f.Write(JSON)

            if err != nil {

                log.Fatal(err)

            }

...


慕姐4208626
浏览 238回答 3
3回答

拉莫斯之舞

将开头写入[文件。在文件上创建一个编码器。遍历切片和每个切片的元素。如果它不是第一个切片元素,请写一个逗号。使用编码器对每个切片元素进行编码。写结尾]。_, err := f.WriteString("[")if err != nil {&nbsp; &nbsp; log.Fatal(err)}e := json.NewEncoder(f)first := truefor i := 0; i < 10; i++ {&nbsp; &nbsp; // Create dummy slice data for this iteration.&nbsp; &nbsp; dataToWrite := []struct {&nbsp; &nbsp; &nbsp; &nbsp; Id&nbsp; &nbsp;string&nbsp; &nbsp; &nbsp; &nbsp; Data string&nbsp; &nbsp; }{&nbsp; &nbsp; &nbsp; &nbsp; {fmt.Sprintf("id%d.1", i), fmt.Sprintf("data%d.1", i)},&nbsp; &nbsp; &nbsp; &nbsp; {fmt.Sprintf("id%d.2", i), fmt.Sprintf("data%d.2", i)},&nbsp; &nbsp; }&nbsp; &nbsp; // Encode each slice element to the file&nbsp; &nbsp; for _, v := range dataToWrite {&nbsp; &nbsp; &nbsp; &nbsp; // Write comma separator if not the first.&nbsp; &nbsp; &nbsp; &nbsp; if !first {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _, err := f.WriteString(",\n")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; first = false&nbsp; &nbsp; &nbsp; &nbsp; err := e.Encode(v)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}_, err = f.WriteString("]")if err != nil {&nbsp; &nbsp; log.Fatal(err)}https://go.dev/play/p/Z-T1nxRIaqL如果将所有 slice 元素保存在内存中是合理的,则通过在单个批次中对所有数据进行编码来简化代码:type Item struct {&nbsp; &nbsp; Id&nbsp; &nbsp;string&nbsp; &nbsp; Data string}// Collect all items to write in this slice.var result []Itemfor i := 0; i < 10; i++ {&nbsp; &nbsp; // Generate slice for this iteration.&nbsp; &nbsp; dataToWrite := []Item{&nbsp; &nbsp; &nbsp; &nbsp; {fmt.Sprintf("id%d.1", i), fmt.Sprintf("data%d.1", i)},&nbsp; &nbsp; &nbsp; &nbsp; {fmt.Sprintf("id%d.2", i), fmt.Sprintf("data%d.2", i)},&nbsp; &nbsp; }&nbsp; &nbsp; // Append slice generated in this iteration to the result.&nbsp; &nbsp; result = append(result, dataToWrite...)}// Write the result to the file.err := json.NewEncoder(f).Encode(result)if err != nil {&nbsp; &nbsp; log.Fatal(err)}https://go.dev/play/p/01xmVZg7ePc

精慕HU

如果您不关心现有文件,您可以Encoder.Encode像@redblue 提到的那样在整个切片上使用。如果您有一个要附加到的现有文件,最简单的方法是执行您在编辑中显示的内容:Unmarshal或Decoder.Decoder将整个文件放入一个结构片中,将新结构附加到该片中,然后重新解码大量使用Marshalor&nbsp;Encoder.Encode。如果你有大量的数据,你可能要考虑使用JSON Lines来避免拖尾,和]问题,并且每行写一个 JSON 对象。或者,您可以使用常规 JSON,从文件末尾向后查找,这样您就可以覆盖 final&nbsp;],然后编写一个,,新的 JSON 编码结构,最后编写一个,]使文件再次成为有效的 JSON 数组。因此,这在一定程度上取决于您的用例和您采用哪种方法的数据大小。

慕桂英546537

注意这个答案是一个solution或者workaround如果你关心现有文件的内容!这意味着它允许您附加到existing json由您创建的文件API。显然这只适用于相同结构的数组实际工作的 json 格式:[object,...object,]写入文件时,不要写[and ]。只需附加到写入序列化json对象的文件并附加一个,实际文件内容:object,...object,最后在读取文件时[添加和追加]这样你就可以write从多个来源访问文件并且仍然有效JSON还要加载文件并为您的处理器提供有效输入json。我们像这样编写日志文件并json通过REST调用提供一个 vaild,然后对其进行处理(例如通过 a JavaScript Grid)
随时随地看视频慕课网APP

相关分类

Go
我要回答