首页 > 后端开发 > Golang > 如何在不将整个负载加载到内存中的情况下高效解码 JSON 流?

如何在不将整个负载加载到内存中的情况下高效解码 JSON 流?

Barbara Streisand
发布: 2024-12-25 18:44:14
原创
1038 人浏览过

How to Efficiently Decode JSON Streams without Loading the Entire Payload into Memory?

在不读取整个有效负载的情况下解码 JSON 流

在这种情况下,我们需要解码通过 HTTP 流接收的 JSON 数据而不加载整个反应进入记忆。目标是处理单个 JSON 项(在数组中表示为“大对象”),并在收到它们时将它们分派到消息队列。

事件驱动的 JSON 解析

为了实现这一点,我们使用 json.Decoder 及其 Decode() 和 Token() 方法。 Decode() 可用于解组单个值,而 Token() 允许我们仅解析 JSON 流中的下一个标记,使我们能够增量处理数据。

On-the- Fly 令牌处理

我们建立一个“状态机”来跟踪我们在 JSON 结构中的位置。通过分析每个标记,我们浏览对象层次结构,识别“items”数组及其大对象元素。

代码实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

package main

 

import (

    "bufio"

    "encoding/json"

    "fmt"

    "io"

    "log"

    "os"

)

 

// Helper error handler

func he(err error) {

    if err != nil {

        log.Fatal(err)

    }

}

 

// Large object struct

type LargeObject struct {

    Id   string `json:"id"`

    Data string `json:"data"`

}

 

func main() {

    // JSON input for demonstration

    in := `{"somefield": "value", "otherfield": "othervalue", "items": [ {"id": "1", "data": "data1"}, {"id": "2", "data": "data2"}, {"id": "3", "data": "data3"}, {"id": "4", "data": "data4"}]}`

 

    dec := json.NewDecoder(strings.NewReader(in))

 

    // Expect an object

    t, err := dec.Token()

    he(err)

    if delim, ok := t.(json.Delim); !ok || delim != '{' {

        log.Fatal("Expected object")

    }

 

    // Read props

    for dec.More() {

        t, err = dec.Token()

        he(err)

        prop := t.(string)

        if t != "items" {

            var v interface{}

            he(dec.Decode(&v))

            fmt.Printf("Property '%s' = %v\n", prop, v)

            continue

        }

 

        // It's the "items". Expect an array

        t, err = dec.Token()

        he(err)

        if delim, ok := t.(json.Delim); !ok || delim != '[' {

            log.Fatal("Expected array")

        }

        // Read items (large objects)

        for dec.More() {

            // Read next item (large object)

            lo := LargeObject{}

            he(dec.Decode(&lo))

            fmt.Printf("Item: %+v\n", lo)

        }

        // Array closing delim

        t, err = dec.Token()

        he(err)

        if delim, ok := t.(json.Delim); !ok || delim != ']' {

            log.Fatal("Expected array closing")

        }

    }

 

    // Object closing delim

    t, err = dec.Token()

    he(err)

    if delim, ok := t.(json.Delim); !ok || delim != '}' {

        log.Fatal("Expected object closing")

    }

}

登录后复制

示例输出

1

2

3

4

5

6

Property 'somefield' = value

Property 'otherfield' = othervalue

Item: {Id:1 Data:data1}

Item: {Id:2 Data:data2}

Item: {Id:3 Data:data3}

Item: {Id:4 Data:data4}

登录后复制

通过使用这种事件驱动的解析方法,我们可以有效地处理大的 JSON 增量响应,避免过多的内存消耗。

以上是如何在不将整个负载加载到内存中的情况下高效解码 JSON 流?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板