forked from DataDog/datadog-agent
/
raw_object_writer.go
121 lines (101 loc) · 3.38 KB
/
raw_object_writer.go
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2019-present Datadog, Inc.
package json
import (
"errors"
jsoniter "github.com/json-iterator/go"
)
// RawObjectWriter contains helper functions to write JSON using the raw API.
type RawObjectWriter struct {
stream *jsoniter.Stream
requireSeparatorByScope [8]bool
scopeLevel int
}
// NewRawObjectWriter creates a new instance of RawObjectWriter
func NewRawObjectWriter(stream *jsoniter.Stream) *RawObjectWriter {
writer := &RawObjectWriter{stream: stream, scopeLevel: -1}
return writer
}
// EmptyPolicy defines the behavior when adding an empty string
type EmptyPolicy int
const (
// OmitEmpty does not write the field if the string is empty
OmitEmpty EmptyPolicy = iota
// AllowEmpty writes the string even if the string is empty
AllowEmpty
)
// StartObject starts a new JSON object (add '{')
func (writer *RawObjectWriter) StartObject() error {
writer.writeSeparatorIfNeeded()
writer.stream.WriteObjectStart()
return writer.addScope()
}
// FinishObject finishes a JSON object (add '}')
func (writer *RawObjectWriter) FinishObject() error {
writer.stream.WriteObjectEnd()
return writer.removeScope()
}
// AddStringField adds a new field of type string
func (writer *RawObjectWriter) AddStringField(fieldName string, value string, policy EmptyPolicy) {
if value != "" || policy == AllowEmpty {
writer.writeSeparatorIfNeeded()
writer.stream.WriteObjectField(fieldName)
writer.stream.WriteString(value)
}
}
// AddInt64Field adds a new field of type int64
func (writer *RawObjectWriter) AddInt64Field(fieldName string, value int64) {
writer.writeSeparatorIfNeeded()
writer.stream.WriteObjectField(fieldName)
writer.stream.WriteInt64(value)
}
// StartArrayField starts a new field of type array
func (writer *RawObjectWriter) StartArrayField(fieldName string) error {
writer.writeSeparatorIfNeeded()
writer.stream.WriteObjectField(fieldName)
writer.stream.WriteArrayStart()
return writer.addScope()
}
// FinishArrayField finishes an array field
func (writer *RawObjectWriter) FinishArrayField() error {
writer.stream.WriteArrayEnd()
return writer.removeScope()
}
// AddStringValue adds a string (for example inside an array)
func (writer *RawObjectWriter) AddStringValue(value string) {
writer.writeSeparatorIfNeeded()
writer.stream.WriteString(value)
}
// Flush the stream
func (writer *RawObjectWriter) Flush() error {
return writer.stream.Flush()
}
func (writer *RawObjectWriter) toString() string {
return string(writer.stream.Buffer())
}
func (writer *RawObjectWriter) writeSeparatorIfNeeded() {
if writer.scopeLevel >= 0 && writer.scopeLevel < len(writer.requireSeparatorByScope) {
if writer.requireSeparatorByScope[writer.scopeLevel] {
writer.stream.WriteMore()
} else {
writer.requireSeparatorByScope[writer.scopeLevel] = true
}
}
}
func (writer *RawObjectWriter) addScope() error {
writer.scopeLevel++
if writer.scopeLevel >= len(writer.requireSeparatorByScope) {
return errors.New("Too many scopes")
}
writer.requireSeparatorByScope[writer.scopeLevel] = false
return nil
}
func (writer *RawObjectWriter) removeScope() error {
if writer.scopeLevel < 0 {
return errors.New("No scope to remove")
}
writer.scopeLevel--
return nil
}